Spring的AOP思想的全面讲解(包含概念、注解和xml两种方式的实现)_chenjie的博客
一、Spring的AOP
AOP的思想:是Aspect oritention programming面想切面编程的简写。把一个个横切关注点(零散存在于业务方法中的功能代码)放进某一个模块中去,我们称这个模块为一个切面。每一个切面都能影响业务的某一个功能,切面的目的就是为了增强。
AOP的目的:AOP能将与业务无关、但是又为业务模块所共同调用的逻辑或其他内容进行封装;减少代码重复率,降低模块之间的耦合度,提高后期的可维护性。
AOP的优势:降低模块的耦合度、让系统更容易扩展、提高后期可维护度。换句话说就是,把多个方法前后相同的代码抽取出来,使用动态代理的方式来控制。运行的时候,先执行抽取出来的方法,再执行真实的方法。
AOP中的一些概念:
Joinpoint:连接点,被拦截到需要被增强的方法。where:去哪里做增强
Pointcut:切入点,哪些包中的哪些类中的哪些方法,可认为是连接点的集合。where:去哪些地方做增强
Advice:增强,当拦截到Joinpoint之后,在方法执行的什么时机(when)做什么样(what)的增强。
Aspect:切面,Pointcut+Advice,去哪些地方+在什么时候+做什么增强
Weaving:织入,把Advice加到Target上之后,创建出Proxy对象的过程。
使用AOP之前,下面三中方法中(权限控制、日志控制、事务控制),存在大量的代码冗余,不利于后期维护。
使用AOP之后,抽取共同的代码部分(权限控制、日志控制、事务控制),需要使用的时候再插入,可大大降低重复代码量,提高后期的可维护性。
二、PointCut语法
PointCut语法的作用,就是为了表达在哪些方法上,使用哪些方法对它进行增强。
AspectJ切入点语法如下:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?)
翻译成中文:
execution(<访问修饰符>? <返回类型> <声明类型>? <方法名>(<参数>) <异常>?)
?:表示可以出现一次,或者不出现.没有问号,表示必须出现一次.
通配符:
*:匹配任何部分,只能表示一个单词
…: 可用于全限定名中和方法参数中,分别表示子包和0到N个参数
举例:
1、表示所有的public方法
execution(public * *(..))
2、表示所有以set开头方法
execution(* set*(..))
3、表示所有由method接口定义的任何方法
execution(* com.xyz.service.method*(..))
4、表示所有在service包下的方法
execution(* com.xyz.service.*.*(..))
5、表示所有在service包下,包括其子包中的方法
execution(* com.xyz.service..*.*(..))
三、使用xml方式实现AOP
1、导入依赖包
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.6.RELEASE</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.5</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.2.6.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13</version> </dependency> </dependencies>
2、创建包、类,目录结构如下:
3、各个类中方法的撰写
Transaction类(需要被增强的类),里面包含两个方法,一个能正常执行的insert()方法,一个主动抛出异常的delete()方法。
public class Transaction { public void insert(){ System.out.println("插入数据!!!"); } public void delete(){ System.out.println("删除数据!!!"); System.out.println(1/0); } }
TransactionManager类(使用里面的方法,去增强其他的类),里面包含四个方法,在不同时期对需要被增强的方法进行增强。
public class TransactionManager { public void before(){ System.out.println("before前置增强!"); } public void afterReturning(){ System.out.println("afterReturning后置增强!"); } public void throwing(){ System.out.println("throwing异常增强!"); } public void after(){ System.out.println("after最终增强!"); } }
applicationContext.xml文件
<!--把这两个类交给spring管理 --> <bean id="transaction" class="com.springaop.service.Transaction"></bean> <bean id="transactionManager" class="com.springaop.tx.TransactionManager"></bean> <!--AOP配置 --> <aop:config> <!--表示哪里的方法需要进行增强--> <aop:pointcut id="txPointCut" expression="execution(* com.springaop.service.*.*(..))"/> <!--增强的方法从哪个类中获取--> <aop:aspect ref="transactionManager"> <!--四种增强方法--> <aop:before method="before" pointcut-ref="txPointCut"/> <aop:after-returning method="afterReturning" pointcut-ref="txPointCut"/> <aop:after-throwing method="throwing" pointcut-ref="txPointCut"/> <aop:after method="after" pointcut-ref="txPointCut"/> </aop:aspect> </aop:config>
TransactionTest测试类
//使用spring的测试方式 @RunWith(SpringJUnit4ClassRunner.class) //导入spring配置文件 @ContextConfiguration("classpath:applicationContext.xml") public class TransactionTest { @Autowired private ApplicationContext context; @Test public void test1(){ Transaction transaction = context.getBean(Transaction.class); transaction.insert(); } @Test public void test2(){ Transaction transaction = context.getBean(Transaction.class); transaction.delete(); } }
运行结果:
1、test1()方法的执行结果如下,可以看到该方法正常执行,增强方法也执行了。
2.test2()方法的执行结果如下,可以看到,我们主动编写的除零异常产生了,于是执行了异常增强方法。
四、使用注解方式实现AOP
1、导入依赖包
同上
2、创建类和包
同上
3、各个类中方法的撰写
Transaction类:同上
TransactionManager类(类上贴上Aspect注解,每个方法都贴上对应增强时期的注解)
@Aspect public class TransactionManager { @Before("execution(* com.springaop.service.Transaction.*(..))") public void before(){ System.out.println("before前置增强!"); } @AfterReturning("execution(* com.springaop.service.Transaction.*(..))") public void afterReturning(){ System.out.println("afterReturning后置增强!"); } @AfterThrowing("execution(* com.springaop.service.Transaction.*(..))") public void throwing(){ System.out.println("throwing异常增强!"); } @After("execution(* com.springaop.service.Transaction.*(..))") public void after(){ System.out.println("after最终增强!"); } }
applicationContext.xml文件,开启AOP注解扫描即可
<!--把这两个类交给spring管理 --> <bean id="transaction" class="com.springaop.service.Transaction"></bean> <bean id="transactionManager" class="com.springaop.tx.TransactionManager"></bean> <!--AOP注解扫描 --> <aop:aspectj-autoproxy/>
TransactionTest测试类,同上
运行结果:
1、test1()方法的执行结果如下,正常执行。
2.test2()方法的执行结果如下,达到预期效果。
- spring系列(二)——AOP的两种实现方式(xml和注解)
- spring aop相关概念和xml与注解实现方式
- 理解Spring AOP并使用XML及注解两种方式实现Spring AOP
- SpringAOP的xml和注解两种实现方式
- AOP实现_AOP中的概念_注解方式_XML配置方式声明切面
- 【Spring aop】Spring aop的XML和注解的两种配置实现
- 【Spring aop】Spring aop的XML和注解的两种配置实现
- Spring系列之 (六):Spring实现IOC的两种方式(XML和注解)
- Spring 详解(二)------- AOP关键概念以及两种实现方式
- Spring框架实现AOP的xml和注解两种方式
- Spring系列(四):Spring AOP详解和实现方式(xml配置和注解配置)
- spring aop注解与xml配置两种方式
- Spring 管理hibernate事物,xml配置,注解 两种实现方式
- Spring的AOP分为注解和配置两种方式实现
- 实例说明Spring实现AOP的2种方式(注解和XML配置)
- Spring AOP 使用注解的方式实现用户日志的两种方法
- spring AOP自定义注解方式实现日志管理的实例讲解
- Spring AOP AspectJ注解和XML配置两种实现(Maven构建)
- servlet调用spring容器中的bean,的两种方式一种注解一种xml配置
- 用Spring配置文件或者注解方式实现AOP