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> <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注解来定义自己的Advice。Spring AOP支持几种不同类型的Advice,包括Before Advice、After Advice、Around Advice等。以下是实现自定义Advice的步骤:
- 创建一个普通的
Java类,当作我们的切面。
- 在这个类中,我们可以定义对应的
Advice方法。
- 我们在
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>) > 使用注解写Advice与xml配置(使用<aop:aspect>)