伍佰目录 短网址
  当前位置:海洋目录网 » 站长资讯 » 站长资讯 » 文章详细 订阅RssFeed

Spring AOP实现原理

来源:本站原创 浏览:104次 时间:2022-10-22
一、AOP是什么?

AOP(Aspect Orient Programming),我们一般称为面向方面(切面)编程,作为面向对象的一种补充,用于处理系统中分布于各个模块的横切关注点,比如事务管理、日志、缓存等等。AOP实现的关键在于AOP框架自动创建的AOP代理,AOP代理主要分为静态代理和动态代理,静态代理的代表为AspectJ;而动态代理则以Spring AOP为代表。本文会分别对AspectJ和Spring AOP的实现进行分析和介绍。

二、springaop如何实现的?

Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK动态代理的核心是InvocationHandler接口和Proxy类。

如果目标类没有实现接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意,CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。

2.1、JDK动态代理

定义一个接口类

package org.java.base.springaop;public interface Service { /** * add方法 */ public void add(); /** * update方法 */ public void update();}

实现一个接口类

package org.java.base.springaop;public class ServiceImpl implements Service {  public void add() { System.out.println("AService add>>>>>>>>>>>>>>>>>>"); } public void update() { System.out.println("AService update>>>>>>>>>>>>>>>"); }}

实现动态代理类MyInvocationHandler,实现InvocationHandler接口,并且实现接口中的invoke方法。仔细看invoke方法,就是在该方法中加入切面逻辑的。目标类方法的执行是由mehod.invoke(target,args)这条语句完成。

package org.java.base.springaop;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class MyInvocationHandler implements InvocationHandler { private Object target; /** * 构造函数 * @param target */ MyInvocationHandler(Object target) { super(); this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 程序执行前加入逻辑,MethodBeforeAdviceInterceptor System.out.println("before-----------------------------"); // 程序执行 Object result = method.invoke(target, args); // 程序执行后加入逻辑,MethodAfterAdviceInterceptor System.out.println("after------------------------------"); return result; }}

测试类,其中增强的目标对象是由Proxy.newProxyInstance(aService.getClass().getClassLoader(),aService.getClass().getInterfaces(), handler);来生成的。

package org.java.base.springaop;import java.lang.reflect.Proxy;public class Test { public static void main(String[] args) { Service aService = new ServiceImpl(); MyInvocationHandler handler = new MyInvocationHandler(aService); // Proxy为InvocationHandler实现类动态创建一个符合某一接口的代理实例 Service aServiceProxy = (Service) Proxy.newProxyInstance(aService .getClass().getClassLoader(), aService.getClass() .getInterfaces(), handler); // 由动态生成的代理对象来aServiceProxy 代理执行程序,其中aServiceProxy 符合Service接口 aServiceProxy.add(); System.out.println(); aServiceProxy.update();  }}

可以看到,在目标类ServiceImpl的add和update方法前后已经加入了自定义的切面逻辑,AOP拦截机制生效了。

2.2、CGLIB动态代理

目标类,cglib不需要定义目标类的统一接口

package org.java.base.springaop;public class Base { /** * 一个模拟的add方法 */ public void add() { System.out.println("add ------------"); }}

实现动态代理类CglibProxy,需要实现MethodInterceptor接口,实现intercept方法。该代理中在add方法前后加入了自定义的切面逻辑,目标类add方法执行语句为proxy.invokeSuper(object, args);

package org.java.base.springaop;import java.lang.reflect.Method;import org.springframework.cglib.proxy.MethodInterceptor;import org.springframework.cglib.proxy.MethodProxy;public class CglibProxy implements MethodInterceptor { public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable { // 添加切面逻辑(advise),此处是在目标类代码执行之前,即为MethodBeforeAdviceInterceptor。 System.out.println("before-------------"); // 执行目标类add方法 proxy.invokeSuper(object, args); // 添加切面逻辑(advise),此处是在目标类代码执行之后,即为MethodAfterAdviceInterceptor。 System.out.println("after--------------"); return null; }}

获取增强的目标类的工厂Factory,其中增强的方法类对象是有Enhancer来实现的,代码如下所示:

 package org.java.base.springaop;import org.springframework.cglib.proxy.Enhancer;public class Factory { /** * 获得增强之后的目标类,即添加了切入逻辑advice之后的目标类 *  * @param proxy * @return */ public static Base getInstance(CglibProxy proxy) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(Base.class); //回调方法的参数为代理类对象CglibProxy,最后增强目标类调用的是代理类对象CglibProxy中的intercept方法 enhancer.setCallback(proxy); // 此刻,base不是单纯的目标类,而是增强过的目标类 Base base = (Base) enhancer.create(); return base; }}

测试类

package org.java.base.springaop;public class Testcglib { public static void main(String[] args) { CglibProxy proxy = new CglibProxy(); // base为生成的增强过的目标类 Base base = Factory.getInstance(proxy); base.add(); }}

自此,cglib动态代理实现的AOP拦截机制已经基本实现,下面我们来看一下拦截的效果如何,程序执行结果如下:

before————-

add ————

after————–

可以看到,在目标类Base的add方法前后已经加入了自定义的切面逻辑,AOP拦截机制生效了。

三、关于动态代理和CGLIB这两种方式的简要总结如下:
  • JDK动态代理(Dynamic Proxy)

    • 基于标准JDK的动态代理功能

    • 只针对实现了接口的业务对象

  • CGLIB

    • 通过动态地对目标对象进行子类化来实现AOP代理,

    • 需要指定@EnableAspectJAutoProxy(proxyTargetClass = true)来强制使用

    • 当业务对象没有实现任何接口的时候默认会选择CGLIB


  推荐站点

  • At-lib分类目录At-lib分类目录

    At-lib网站分类目录汇集全国所有高质量网站,是中国权威的中文网站分类目录,给站长提供免费网址目录提交收录和推荐最新最全的优秀网站大全是名站导航之家

    www.at-lib.cn
  • 中国链接目录中国链接目录

    中国链接目录简称链接目录,是收录优秀网站和淘宝网店的网站分类目录,为您提供优质的网址导航服务,也是网店进行收录推广,站长免费推广网站、加快百度收录、增加友情链接和网站外链的平台。

    www.cnlink.org
  • 35目录网35目录网

    35目录免费收录各类优秀网站,全力打造互动式网站目录,提供网站分类目录检索,关键字搜索功能。欢迎您向35目录推荐、提交优秀网站。

    www.35mulu.com
  • 就要爱网站目录就要爱网站目录

    就要爱网站目录,按主题和类别列出网站。所有提交的网站都经过人工审查,确保质量和无垃圾邮件的结果。

    www.912219.com
  • 伍佰目录伍佰目录

    伍佰网站目录免费收录各类优秀网站,全力打造互动式网站目录,提供网站分类目录检索,关键字搜索功能。欢迎您向伍佰目录推荐、提交优秀网站。

    www.wbwb.net