SpringAOP源码阅读-创建AOP代理的3个工厂

今天我们介绍一下创建AOP代理的3个工厂,它们分别是

  • ProxyFactory
  • ProxyFactoryBean
  • AspectJProxyFactory

基础内容

  1. 目标类
public class TestService {
    public void sayHello() {
        System.out.println("hello world");
    }
}
  1. 通知
public class XiXiMethodInterceptor implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("before");
        return invocation.proceed();
    }
}

ProxyFactory

public class ProxyFactoryMain {
    public static void main(String[] args) {
        ProxyFactory proxyFactory = new ProxyFactory();
        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
        advisor.setAdvice(new XiXiMethodInterceptor());
        //advisor.setPointcut(); //默认匹配所有类所有方法
        proxyFactory.addAdvisor(advisor);

        TestService testService = new TestService();
        proxyFactory.setTarget(testService);

        TestService proxy = (TestService) proxyFactory.getProxy();
        proxy.sayHello();
    }
}

设置目标类 设置Advisor

SpringAOP源码阅读-创建AOP代理的3个工厂
image.png

ProxyFactoryBean

public class ProxyFactoryBean extends ProxyCreatorSupport
  implements FactoryBean<Object>, BeanClassLoaderAwareBeanFactoryAware 
{
            
}

ProxyFactoryBean它是一个FactoryBean,自然会调用其getObject()

public class ProxyFactoryBeanMain {
    public static void main(String[] args) {
        ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
        advisor.setAdvice(new XiXiMethodInterceptor());
        //advisor.setPointcut(); //默认匹配所有类所有方法
        proxyFactoryBean.addAdvisor(advisor);

        TestService testService = new TestService();
        proxyFactoryBean.setTarget(testService);

        TestService proxy = (TestService) proxyFactoryBean.getObject();
        proxy.sayHello();
    }
}

设置目标类 设置Advisor 调用getObject()

SpringAOP源码阅读-创建AOP代理的3个工厂
image.png

AspectJProxyFactory

@Aspect
public class XiXiAspect {
    @Pointcut("execution(public * *(..))")
    public void pointCut(){
    }
    @Before("pointCut()")
    public void before(){
        System.out.println("aspectJ before");
    }
}
public class AspectJProxyFactoryMain {
    public static void main(String[] args) {
        AspectJProxyFactory proxyFactory = new AspectJProxyFactory();
        //先设置target、再设置Aspect顺序不能乱
        proxyFactory.setTarget(new TestService());
        proxyFactory.addAspect(new XiXiAspect());
        TestService proxy = (TestService) proxyFactory.getProxy();
        proxy.sayHello();
    }
}

设置Aspect<=>Advisor<=>Advice+PointCut设置目标类

SpringAOP源码阅读-创建AOP代理的3个工厂
image.png

DefaultAopProxyFactory

不论是ProxyFactoryProxyFactoryBean或者AspectJProxyFactory最终都会调用DefaultAopProxyFactory#createAopProxy(AdvisedSupport config)方法去创建AOP代理。

public class DefaultAopProxyFactory implements AopProxyFactorySerializable {

 private static final long serialVersionUID = 7930414337282325166L;


 @Override
 public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
  if (!NativeDetector.inNativeImage() &&
    (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
   Class<?> targetClass = config.getTargetClass();
   if (targetClass == null) {
    throw new AopConfigException("TargetSource cannot determine target class: " +
      "Either an interface or a target is required for proxy creation.");
   }
   if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {
    return new JdkDynamicAopProxy(config);
   }
   return new ObjenesisCglibAopProxy(config);
  }
  else {
   return new JdkDynamicAopProxy(config);
  }
 }
}

可以看到可能会返回2种代理

  • ObjenesisCglibAopProxy:Cglib代理
  • JdkDynamicAopProxy:JDK代理

我们看到if判断config.isProxyTargetClass()也就是对应启动注解中的属性@EnableAspectJAutoProxy(proxyTargetClass = true)

总结

好了,今天我们就简单介绍了手动创建AOP代理的三个类以及它们都使用到的一个DefaultAopProxyFactory。谢谢大家的阅读。


原文始发于微信公众号(溪溪技术笔记):SpringAOP源码阅读-创建AOP代理的3个工厂

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/207146.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!