1.Spring aop的定义:
Spring aop是spring的2大核心之一,又叫面向切面编程,是对oop的一种完善。通俗地说就是不改变原来的类的功能,额外地增加功能。所以aop采用的是动态代理模式:有java动态代理模式(默认),cglib动态代理模式。
当需要代理的类不是接口类型的时候,Spring会自动切换为CGLIB来进行代理,也可以强制的选择使用CGLIB来进行代理- 动态代理分为两种:
- * java的动态代理
- * 代理对象和目标对象实现了共同的接口
- * 拦截器必须实现InvocationHanlder接口
- * cglib的动态代理
- cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理
- * 代理对象是目标对象的子类
- * 拦截器必须实现MethodInterceptor接口
动态代理模式的优势:实现无侵入式的代码扩展
2.spring aop的核心:
1.横切关注点
2.切面
3.连接点
4.切入点
5.通知:(前置通知,后置通知,环绕通知,最终通知,异常通知)
6.目标对象
7.织入
8.引入
3.实现aop编程步骤:
1.定义业务组件(bean)
2.定义切入点(aop:pointcut)
3.定义增强处理(5大通知增强方法)
4.实现spring-aop例子,有xml配置实现和注解方式实现
1.xml配置实现:
1.写student接口(Student.class),实现student接口类(Students.class),切面类1(AopAspect.class),切面类2(AopAspect2.class),测试类(AopTest.class),xml配置文件(student-aop.xml)
student接口
接口实现类
切面类1:xml用<aop:aspect/>时
切面类2:主要是xml配置中如果用<aop:advisor/>的话,切面类要实现advice接口
编写student-aop.xml
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
<!-- 使用xml配置方式实现aop -->
<bean id="stu" class="dorm.aop2.Students"></bean>
<bean id="aspect" class="dorm.aop2.AopAspect"></bean>
<bean id="aspect2" class="dorm.aop2.AopAspect2"></bean>
<aop:config>
<!-- < aop:aspect>:定义切面(切面包括通知和切点)大多用于日志,缓存
< aop:advisor>:定义通知器(通知器跟切面一样,也包括通知和切点)大多用于事务管理。
< aop:aspect>定义切面时,只需要定义一般的bean就行,
而定义< aop:advisor>中引用的通知时,通知必须实现Advice接口。 -->
<!-- 配置切入点 dorm.aop2.Student该接口的所有方法 -->
<aop:pointcut expression="execution(* dorm.aop2.Student.*(..))"
id="allMethod" />
<aop:advisor advice-ref="aspect2" pointcut-ref="allMethod" />
<!-- 配置切面类 -->
<aop:aspect id="aspectClass" ref="aspect">
<!-- 定义前置增强方法 -->
<aop:before method="breakFast" pointcut-ref="allMethod" />
<!-- 定义后置增强方法 -->
<aop:after method="play" pointcut-ref="allMethod" />
<!-- 定义环绕增强方法,使用匿名切点,切入点为finishClass方法,使用接口finishClass方法才执行环绕通知 -->
<aop:around method="plays"
pointcut="execution(* dorm.aop2.Student.finishClass(..))" />
</aop:aspect>
<aop:aspect id="aspectClass2" ref="aspect">
<aop:around method="plays"
pointcut="execution(* dorm.aop2.Student.leaveSchool(..))" />
</aop:aspect>
</aop:config>
</beans>
编写测试类
测试结果:
2.使用注解方式实现:
1.对象类Student,2.切面类StudentAspect,3.配置xml文件:aopAnnotion.xml
Student类