【Spring】AOP实现及原理

5).Spring AOP编程:动态代理

(1)引言(静态代理):
现有代码的问题:
①事务代码耦合: 现有的事务控制的代码,耦合在了service方法中,一旦数据库访问技术发生变化,所
有事务控制代码需要替换,导致service的代码被大量的修改
②事务控制的代码冗余: 大量相同的事务控制代码出现在了service方法中,出现冗余代码,不利于后期的升级和维护
解决思路: 通过手动添加代理类,将事务控制代码放在代理类中
代理类的核心规范 · 静态代理[重点]
① 先和目标类实现相同的接口
② 将额外功能(事务控制),放在代理类中
③ 调用目标对象的目标方法
④ 代替目标对象接受调用
作用:将事务代码和service的核心功能代码解耦和
缺点:每个目标类都要书写一个代理类,存在代码冗余
(2)动态代理
动态代理: 使用技术动态为目标类生成代理类
代理类核心:
① 额外功能(事务控制等)
② 调用目标对象的方法
③ 和目标类拥有相同的接口
Springaop技术的核心思想:
① 将额外功能的代码放在功能增强的对象中
② Spring AOP技术,将功能增强中的额外功能的代码,动态生成代理类,添加进去
spring AOP的步骤:
准备: 导入spring AOP依赖的jar(`asm.jar`  `cglib.jar`  `aspectj.awear.RELEASE.jar`)
①准备目标类(例如service)
②书写额外功能所在的 功能增强类
  public class 增强类 implements org.aopalliance.intercept.MethodInterceptor{
   	@Override
   	public Object invoke(MethodInvocation mi) throws Throwable {
   		//1. 开启事务
   		//2. 调用目标对象的功能。
   		Object o = mi.proceed();//调用真正的目标对象的方法
   		//3. 提交事务
   		return o;
   	}
  }
③通过aop技术,动态生成代理类 = 额外功能+目标对象
  核心:① 额外功能加入的位置: 切入点,是告诉spring将额外功能代码放在哪个方法的内部[告诉spring将额外功能加入哪个类的哪个方法中② 组装: 额外功能+类、方法(切入点)==代理类
例子:
   	<!-- 1 管理目标对象UserServiceImpl -->
	<bean id="us" class="com.jwnming.UserServiceImpl"></bean>
	<!-- 2 管理增强类UserServiceImplZengqiang -->
	<bean id="zengqiang" class="com.jwnming.UserServiceImplZengqiang"></bean>
	<!-- 3 为us对象产生代理类,代理对象 :切入点、组装-->
	<aop:config>
		<!-- 切入点:明确目标类和目标方法 -->
		<aop:pointcut id="pc" expression="execution(void com.jwnming.UserServiceImpl.regist())"></aop:pointcut>
		<!-- 组装 -->
		<aop:advisor pointcut-ref="pc" advice-ref="zengqiang"></aop:advisor>
	</aop:config>		

6).Spring AOP编程思想、MethodInterceptor接口详解

(1)SpringAOP编程思想
AOP:aspect orinted programing 面向切面编程,在不修改目标的代码的情况下,动态的为目标类的方法添加额外的功能代码
本质:使用jdk技术,动态为目标类生成了代理类的,生成代理的对象,使用生成的代理对象替换了你的原始的目标对象
(2)MethodInterceptor详解
public class XxxAdvice implements MethodInterceptor{
	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {    	//mi: 代表目标对象的方法
        Object o = mi.proceed();//调用目标对象的目标方法
		return o;
	}
}
① 获得目标对象的方法:mi.getMethod();	//Method 类型的目标方法
② 目标对象:mi.getThis();			//获得目标对象
③ 获得代理的目标方法的调用时,实际传入的参数:mi.getArguments();	//数组,实际传入的参数
④ 调用目标对象的目标方法:Object o = mi.proceed();	//us.regist()     ps.add()
	注:① 调用目标对象的方法 ② 返回值代表实际被代理的方法的返回值

7).Spring的<aop:pointcut>标签几种切入点表达式

切入点表达式详解
pointcut切入点: 告诉spring功能增强的目标类的目标方法
标签:<aop:pointcut  id=""  expression="切入点表达式"></aop:pointcut>
(1)execution
特点: 精确到方法声明的
① 精确点指定包指定类指定方法。
execution(返回值 包名.子包.孙子包.类.方法名(参数1类型,参数2类型)); //参数类型之间用逗号隔开
② 精确到指定包下的指定类的执行方法,参数任意:
execution(返回值 包名.子包.孙子包.类.方法名(..));
③ 精确到指定包的指定类,方法名任意,参数类型任意
execution(返回值 包名.子包.孙子包.类.*(..));
④ 精确指定包下的任意类,任意方法,任意参数类型
execution(返回值 包名.子包.孙子包.*.*(..));
⑤ 精确到指定包下的类,及其子包下的所有类的任意方法,任意参数,任意返回值类型
execution(* p1.p2.p3..*.*(..));
(2)within
语法: expression="within(表达式语法)"
特点: 表达式的写法,只精确到类
① 指定包下的类:				within(包名.类名);
② 指定包及其子包下的所有类:	within(p1.p2.p3..*);
(3)@annotation
语法: expression="@annotation(注解全类名)"
特点: 凡是添加指定注解的方法,都会被功能增强
使用步骤:
① 定义注解:public @interface HeheAdvice { }   //定义:添加了HeheAdvice注解的方法,都会被功能增强
② 使用注解:给需要功能增强的方法添加注解,例a1方法
public class AServiceImpl{
	@HeheAdvice
	public void a1(){}
}
③ 通过切入点,指定:添加@HeheAdvice的方法,进行功能增强
	<aop:pointcut  id=""  expression="@annotation(注解名的全类名)"></aop:pointcut>
posted @ 2020-09-08 20:26  JWnMing  阅读(145)  评论(0编辑  收藏  举报