spring中aop总结(一)

项目背景

​ 在这里我就是一个简单的spring项目,主要是想要使用jdbcTemplate从数据库中查询class表的总行数。在这里我们想要岁这个方法进行增强。实现aop效果。

对于jar包的解释:

​ 如果你使用的是 XML 配置来定义切面和通知,你需要引入 spring-aop 包。spring-aop 包是Spring框架的核心AOP模块,它提供了基本的AOP功能,包括切面、通知、切点等。通过引入 spring-aop 包,你可以使用 XML 配置来实现 AOP 功能。

​ 如果你需要使用@Aspect注解来定义切面,你需要引入spring-aspects包。spring-aspects包是Spring框架提供的一个可选模块,它包含了AspectJ注解所需的类和工具。通过引入spring-aspects包,你可以方便地使用@Aspect注解来定义切面、通知和切点,从而实现更加灵活和强大的AOP功能。请确保在你的项目中添加了spring-aspects的依赖,以便使用@Aspect注解。

pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.example</groupId>
<artifactId>aop_sum</artifactId>
<version>1.0-SNAPSHOT</version>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.23</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.3.23</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.23</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.3.23</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.32</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.3.23</version>
</dependency>
</dependencies>
</project>

基本代码:

ClassDao.class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.zgy.aop.dao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository
public class ClassDao {
@Autowired
private JdbcTemplate template;

public int selectCount(){
return template.queryForObject("select count(1) from class;",Integer.class);
}
}

SelectCount.java

1
2
3
4
5
6
package com.zgy.aop.service;

public interface SelectCount {
public int selectCount();

}

SelectCountImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.zgy.aop.service.impl;

import com.zgy.aop.dao.ClassDao;
import com.zgy.aop.service.SelectCount;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


@Service
public class SelectCountImpl implements SelectCount {
@Autowired
private ClassDao dao;
public int selectCount() {
return dao.selectCount();
}
}

Test1.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.zgy.aop;


import com.zgy.aop.service.SelectCount;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test1 {
@Test
public void test(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("springConfig.xml");
SelectCount bean = context.getBean(SelectCount.class);
System.out.println(bean.selectCount());
}
}

使用注解配置aop

注解配置很方便,我们只需要在springConfig.xml中开启自动生成aop代理,在自定义一个切面类里面使用注解配置就好了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
<context:component-scan base-package="com.zgy.aop"></context:component-scan>
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" >
<property name="url" value="${jdbc_url}"></property>
<property name="username" value="${jdbc_username}"></property>
<property name="password" value="${jdbc_password}"></property>
<property name="driverClassName" value="${jdbc_driver}"></property>
</bean>

<bean class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

​ 自定义切面类,在类上面使用@Aspect注解来声明我们这个类是切面类。在使用@Pointcut注解定义我们的具体切点,确定我们需要增强的函数。@Before("addPoint()")注解是我们的具体增强功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.zgy.aop.aspect;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class DaoAspect {
@Pointcut("execution(* com.zgy.aop.dao.*.selectCount())")
public void addPoint(){}

@Before("addPoint()")
public void before(){
System.out.println("123123");
}

}

使用xml配置aop

使用xml来完成配置

​ 要实现自定义的Advice,你可以使用Spring AOP中的AspectJ注解来定义自己的AdviceSpring AOP支持几种不同类型的Advice,包括Before AdviceAfter AdviceAround Advice等。以下是实现自定义Advice的步骤:

  1. 创建一个普通的Java类,当作我们的切面。
  2. 在这个类中,我们可以定义对应的Advice方法。
  3. 我们在xml文件中配置切面和切点。

DaoAspect.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.zgy.aop.aspect;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component;

@Component
public class DaoAspect {

public void before(){
System.out.println("123123");
}

}

springConfig.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
<context:component-scan base-package="com.zgy.aop"></context:component-scan>
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" >
<property name="url" value="${jdbc_url}"></property>
<property name="username" value="${jdbc_username}"></property>
<property name="password" value="${jdbc_password}"></property>
<property name="driverClassName" value="${jdbc_driver}"></property>
</bean>

<bean class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>

<aop:config>
<aop:pointcut id="pc" expression="execution(* com.zgy.aop.dao.ClassDao.selectCount())"/>
<aop:aspect ref="daoAspect">
<aop:before method="before" pointcut-ref="pc"></aop:before>
</aop:aspect>
</aop:config>

</beans>

使用xml以及自定义的Advice来完成配置

​ 除了使用AspectJ注解,Spring AOP还提供了其他方式来实现自定义Advice。你可以通过实现org.aopalliance.aop.Advice接口来定义自己的Advice。下面是一个简单的示例代码,演示了如何通过实现Advice接口来定义一个自定义的Before Advice

MyAdvice.java

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.zgy.aop.aspect;

import org.aspectj.weaver.Advice;
import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class MyAdvice implements MethodBeforeAdvice {
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("123123");
}
}

springConfig.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
<context:component-scan base-package="com.zgy.aop"></context:component-scan>
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" >
<property name="url" value="${jdbc_url}"></property>
<property name="username" value="${jdbc_username}"></property>
<property name="password" value="${jdbc_password}"></property>
<property name="driverClassName" value="${jdbc_driver}"></property>
</bean>

<bean class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>

<bean id="myadvice" class="com.zgy.aop.aspect.MyAdvice"></bean>
<aop:config>
<aop:pointcut id="pc" expression="execution(* com.zgy.aop.dao.ClassDao.selectCount())"/>
<aop:advisor advice-ref="myadvice" pointcut-ref="pc"></aop:advisor>
</aop:config>
</beans>

总结

​ 综上几个方法,方便程度:使用注解配置 > 使用实现Advice的自定义通知与xml配置(使用<aop:advisor>) > 使用注解写Advicexml配置(使用<aop:aspect>