当前位置: 首页 > 后端技术 > Java

浅谈SpringAOP

时间:2023-04-01 13:45:54 Java

Spring核心的AOPAOP是什么?AOP(AspectOrientedProgramming)是一种设计思想,是软件设计领域的面向切面编程。它是面向对象(OOP)的补充和完善。它实现了一种通过预编译和运行时动态代理的方式,在不修改源代码的情况下,动态统一地为程序添加附加功能的技术。如图:AOP和OOP从字面意思上很相似,但实际上是针对不同领域的设计思想。在实际项目中,我们通常将面向对象理解为一个静态过程(例如,一个系统有多少个模块,一个系统有多少个模块?模块有哪些对象,对象有哪些属性)。面向切面的运行时代理方法理解为一个动态过程,可以在对象运行时动态地编织一些扩展功能或者控制对象执行。SpringAOP应用原理SpringAOP底层是基于代理机制(动态代理)实现功能扩展的:动态代理:在不改变源码的情况下增强现有方法。1)JDK动态代理:如果目标对象(代理对象)实现了接口,AOP底层可以使用JDK动态代理机制为目标对象创建代理对象(目标对象和代理对象会实现一个通用接口)。2)CGLIB动态代理:如果目标对象(代理对象)没有实现接口,AOP底层会使用CGLIB代理机制为目标对象创建代理对象(默认创建的代理类会继承目标对象类型),注意:继承目标类不能被final修饰。JDK动态代理:要求目标对象至少实现一个接口。涉及到的类有:Proxy创建动态代理的方法是:newProxyInstance(ClassLoader,Class[],InvocationHandler)Useruser=newUserImpl();/***参数含义:*ClassLoader:类加载器,与代理对象使用同一个类加载器;*Class[]:字节码数组,代理类实现的接口(要求代理对象和被代理对象的行为相同);*InvocationHandler:它是一个接口,用于提供增强代码。一般写一个这个接口的实现类。实现类可以是匿名内部类;它的含义是如何代理;*/代理对象接口jdkProxy=(需要强制传输)Proxy.newProxyInstance(user.getClass().getClassLoader(),user.getClass().getInterfaces(),newInvocationHandler(){Objectresult=null/***Any执行代理对象的方法必须经过这个方法,这个方法有拦截的作用;*方法的参数:*对象代理:代理对象的引用,不一定每次都使用*方法method:当前执行的方法*Object[]args:当前执行方法需要的参数*返回值:当前执行方法的返回值*/@OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{//增强业务result=method.invoke(proxiedobject,parametersused);//执行被代理对象的方法//增强业务返回结果;}});jdkProxy.test();//通过代理对象调用代理对象的方法实现业务增强CGLIB动态代理:要求:代理类不能是final类;它不能被final修改;涉及的类:Enhancer创建对象的方法:create(Class,Callback);UserImpluser=newUserImpl();/***参数含义:*Class:被代理的对象字节码*Callback:如何代理,作用与InvocationHandler一样,也是一个接口,*一般使用该接口的子类MethodInterceptor;时间也是创建接口的匿名内部类;*/代理对象cglibProxy=(需要强制)Enhancer.create(user.getClass(),newMethodInterceptor(){Objectresult=null;/***执行代理对象的任意方法,功能同上JDK动态代理的invoke方法*方法参数:*Objectproxy,Methodmethod,Object[]args与invoke的方法参数相同;*MethodProxy:当前执行方法的代理对象,在参数Proxy中Method方法的对象;一般不是*/@OverridepublicObjectintercept(Objectproxy,Methodmethod,Object[]args,MethodProxymethodProxy)throwsThrowable{//业务增强result=method.invoke(user,args);//执行被代理对象的方法//业务增强返回结果;}});cglibProxy.test();//通过代理对象调用代理对象的方法,实现业务增强对象(可以借助@Aspect声明)是pointcut和advice的结合。通知/增强(Advice):对切面的特定连接点执行的动作(扩展功能),实际上就是增强代码。例如:around、before、after等。Joinpoint:程序执行过程中的一个特定点,一般指向拦截的目标方法,其实就是业务类接口中的所有方法。Pointcut:定义多个连接点(Joinpoint),一般可以理解为多个连接点的集合,其实是一种增强的方法。简介:给通知的类添加一个方法或字段。Spring允许向任何建议的对象引入新接口。例如,您可以使用导入使任何对象实现IsModified接口以简化缓存。在Spring中使用Introduction,可以使用DelegatingIntroductionInterceptor实现通知,使用DefaultIntroductionAdvisor配置Advice与代理类的连接。一般不使用。目标对象:包含连接点的对象。也称为建议或代理对象。编织:组装方面以创建建议的对象。这可以在编译时(例如使用AspectJ编译器)或运行时完成。与其他纯JavaAOP框架一样,Spring在运行时进行织入。代理(Proxy):一个类经过AOP编织增强后,生成一个结果代理类;Spring中常用的通知类型:before(预通知):总是在入口点方法执行之前执行;afterReturning(post-notification):入口点方法正常执行后执行;afterThrowing(异常通知):入口点方法执行产生异常后执行;它和post通知只能永远执行;after(finalnotification):无论入口点方法是否正常执行,都会在执行后执行。Around(通知周围):spring框架提供了一种在代码中手动控制通知方法何时执行的方式;spring中为我们提供了一个接口:ProceedingJoinPoint;该接口可以作为周边通知的参数。该接口中有一个方法:proceed(),相当于method.invoke方法,是显式调用业务层的核心方法(入口方法);例如(xml配置方法):publicObjectaroundTest(ProcesdingJoinPointpjp){Objectresult=null;try{System.out.println("预通知");result=pjp.proceed();//调用业务层核心方法System.out.println("Post-notification");}catch(Exceptione){System.out.println("异常通知");}finally{System.out.println("最终通知");}返回结果;}AOP中的切入点表达式:切入点表达式:关键字:execution(expression)表达式写法:访问修饰符返回值包名。包名...类名。方法名(参数列表)全匹配方法:execution(publicvoidcom.service.impl.xxxServiceImpl.save())全通配方法:execution(**..*.*(..));包位置写“..”表示当前包和子包参数写“..”表示是否有参数有,有参数可以是任意类型.在实际开发中,一般会增强业务层的方法,所以一般的写法是:*com.service.impl.*.*(..)generalentrypointExpression:XML基于AOP的配置:基于注解的AOP配置:引入上下文命名空间:配置Spring注册容器时扫描的包:开启spring对注解AOP的支持:AOP业务增强实现:在业务层(目标对象)添加@Service注解并传递overtospringmanagement;通知类需要通过@Component注解标识;使用@Aspect注解表示通知类配置切面通知类方法,并配置通知类型:@Before("pointcutexpression")在这个类中定义了一个切入点表达式:@Pointcut("execution(*com.service.impl.*.*(..))")privatevoidpt(){}//引用切入点表达式@Before("pt()")publicvoidbeforeTest(){System.out.println("预通知业务增强");}