Spring AOP ProxyFactory

所有文章已迁移至csdn,csdn个人主页bugpool.blog.csdn.net

Spring AOP源码目录

Spring AOP源码01:Jdk动态代理底层源码
Spring AOP源码02:ProxyFactory
Spring AOP源码03:JdkDynamicAopProxy
Spring AOP源码04:MethodInvocation 拦截器调用
Spring AOP源码05:DefaultAdvisorAutoProxyCreator
Spring期末考压轴题:当Spring AOP遇上循环依赖
git注释源码地址:https://github.com/chaitou/spring-framework-master.git

前言

本篇将重点剖析ProxyFactory类的源码,很多人不理解为什么要将大部分精力花在讲解ProxyFactory上,毕竟没有人会使用这么底层的Spring AOP实现方式?

ProxyFactory实现代理需要手动设置Traget(目标对象)、Interface(代理接口)、Advice(增强),然后调用getProxy生成代理对象。而使用注解形式的Spring AOP并没有想象中的复杂,不过是寻找所有@Aspect注解的类以及所有@Before等增强,再通过@Pointcut上的匹配条件进行匹配,最后获取到所有匹配的Advice(增强)进行生成代理。因此,注解形式的AOP并不深奥,只不过是帮我们自动寻找匹配增强,并在Spring Ioc创建Bean的过程中寻找合适的时机,调用getProxy生成代理,仅此而已。因此,如果我们将手动硬编码的方式(ProxyFactory)学透了,基本上也就掌握了Spring AOP了,至于注解的形式,我们只需要再探究一下Advice如何获取以及匹配就可以了

剖去注解与Xml的配置,Spring AOP的核心就是ProxyFactory,抓住主线,才能更好的把握源码脉络,不至于被边角的细节所干扰

ProxyFactory

代码示例

我们将会写一个UserService接口,定义findUser方法,同时在before跟after使用Advice(增强)对方法进行增强,最后使用ProxyFactory进行代理的生成。

在这里有必要先大致介绍一下Advice(增强)和Advisor(切面),2个单词长的有点像,但是他们是聚合的关系。

  • 增强(Advice):常见的有Before adviceAfter returning advice,也就是在连接点进行扩展操作
  • 切点(Pointcut):也就是连接点,用于判断当前方法或者类是否需要增强
  • 切面(Advisor):可以看做的增强切点的结合。假设一个方法需要进行增强,则遍历所有切面,调用Pointcut进行判断当前切面是否适用,如果适用,则调用当前Advice进行增强

接口:

public interface UserService {
    public void findUser();
}

实现类:

public class UserServiceImpl implements UserService {
    @Override
    public void findUser() {
        System.out.println("findUser...");
    }
}

2个增强:

// 前置增强
public class LogBeforeAdvice implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("before log...");
    }
}

// 后置增强
public class LogAfterAdvice implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("after log...");
    }
}

测试:

public class UserServiceImplImplTest {
    @Test
    public void findUser() {

        // 1. 创建代理工厂
        ProxyFactory factory = new ProxyFactory();
        // 2. 设置代理目标对象
        factory.setTarget(new UserServiceImpl());
        // 3. 设置接口
        factory.setInterfaces(new Class[]{UserService.class});
        // 4. 设置增强
        factory.addAdvice(new LogBeforeAdvice());
        factory.addAdvice(new LogAfterAdvice());
        // 5. 获取代理对象
        UserService userService = (UserService) factory.getProxy();

        userService.findUser();
    }
}

运行结果:

before log...
findUser...
after log...

Process finished with exit code 0

ProxyFactory继承关系

ProxyFactory

我们重点关心一下类,忽略接口

  • ProxyConfig:用于保存Proxy的相关基础配置,比如是否使用激进模式optimize、强制开起cglib代理proxyTargetClass、是否暴露代理exposeProxy等,在xml配置中十分常见,例如强制开启Cglib代理
  • AdvisedSupport:AOP的配置管理类,比起ProxyConfig,其还保存了targetSource、切面的集合advisors、接口集合interfaces
  • ProxyCreatorSupport:代理工厂的基础类,提供对可配置AopProxyFactory的便捷访问

源码分析

  1. 创建代理工厂,直接调用默认空构造器
  2. 设置代理目标对象,将target对象封装成TargetSource对象,为什么要多此一举呢?其实TargetSource的目的是为了做对象池和多例用的,也就是说每次代理都从池中获取对象。而这里我们只使用SingletonTargetSource,关于TargetSource留到后面讲解。刚刚提到这些属性都是保存在AdvisedSupport中的
    public void setTarget(Object target) {
        setTargetSource(new SingletonTargetSource(target));
    }

    @Override
    public void setTargetSource(@Nullable TargetSource targetSource) {
        this.targetSource = (targetSource != null ? targetSource : EMPTY_TARGET_SOURCE);
    }
  1. 设置接口数组,同样保存到AdvisedSupport的属性中
    public void setInterfaces(Class... interfaces) {
        Assert.notNull(interfaces, "Interfaces must not be null");
        // 先清空再添加
        this.interfaces.clear();
        for (Class ifc : interfaces) {
            addInterface(ifc);
        }
    }

    public void addInterface(Class intf) {
        Assert.notNull(intf, "Interface must not be null");
        // 校验如果不是接口则抛出异常
        if (!intf.isInterface()) {
            throw new IllegalArgumentException("[" + intf.getName() + "] is not an interface");
        }
        if (!this.interfaces.contains(intf)) {
            this.interfaces.add(intf);
            adviceChanged();
        }
    }
  1. 设置Advice,前面我们说过Advice只是增强,因此我们要封装成Advisor切面才能加到AdvisedSupportadvisors集合中。而需要注意的是因为没有配置任何的Pointcut,因此将使用DefaultPointcutAdvisor进行创建
    @Override
    public void addAdvice(Advice advice) throws AopConfigException {
        int pos = this.advisors.size();
        addAdvice(pos, advice);
    }

    @Override
    public void addAdvice(int pos, Advice advice) throws AopConfigException {
        Assert.notNull(advice, "Advice must not be null");
        
        if (advice instanceof IntroductionInfo) {
            // We don't need an IntroductionAdvisor for this kind of introduction:
            // It's fully self-describing.
            // 单独处理引介增强
            addAdvisor(pos, new DefaultIntroductionAdvisor(advice, (IntroductionInfo) advice));
        }
        else if (advice instanceof DynamicIntroductionAdvice) {
            // We need an IntroductionAdvisor for this kind of introduction.
            // DynamicIntroductionAdvice只能作为IntroductionAdvisor的一部分
            throw new AopConfigException("DynamicIntroductionAdvice may only be added as part of IntroductionAdvisor");
        }
        else {
            // 普通增强
            addAdvisor(pos, new DefaultPointcutAdvisor(advice));
        }
    }

DefaultPointcutAdvisor的意思就是无论什么方法都匹配,因此可以看到Pointcut使用的是Pointcut.TRUE,无论匹配什么方法都是true

new DefaultPointcutAdvisor(advice)
// Pointcut.TRUE
// 也就是说该Advisor的匹配均为true,匹配任何的方法,不做任何限制!
public DefaultPointcutAdvisor(Advice advice) {
    this(Pointcut.TRUE, advice);
}
  1. 创建代理,这才是本篇的重头戏
    public Object getProxy() {
        return createAopProxy().getProxy();
    }

代码就createAopProxy().getProxy()一句,在调用getProxy()之前,我们得弄清楚是什么对象调用的getProxy(),换句话说,也就是createAopProxy()到底创建了什么对象

protected final synchronized AopProxy createAopProxy() {
    if (!this.active) {
        activate();
    }
    return getAopProxyFactory().createAopProxy(this);
}
----------------------------------------------------------------
public AopProxyFactory getAopProxyFactory() {
    // 返回的是类中的成员变量aopProxyFactory
    return this.aopProxyFactory;
}
----------------------------------------------------------------
// 成员变量的实例化则是在默认构造器中
private AopProxyFactory aopProxyFactory;

// 构造器,调用了DefaultAopProxyFactory进行实例化,因此aopProxyFactory真正的类型是DefaultAopProxyFactory
public ProxyCreatorSupport() {
    this.aopProxyFactory = new DefaultAopProxyFactory();
}

跟踪发现createAopProxy()返回的是属性aopProxyFactory,而属性aopProxyFactory又是在ProxyCreatorSupport构造器时进行实例化的,真正的类是DefaultAopProxyFactory,因此继续跟踪DefaultAopProxyFactorycreateAopProxy方法

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

    @Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        // isOptimize开启激进模式 || proxyTargetClass=true(强制开启cglib代理) || 接口集合为空
        if (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)) {
                return new JdkDynamicAopProxy(config);
            }
            // 没有接口,只能选择cglib代理
            return new ObjenesisCglibAopProxy(config);
        }
        else {
            // 使用JDK代理
            return new JdkDynamicAopProxy(config);
        }
    }
  ...
}

可以看到,当config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)为真时才会使用Cglib代理,而当代理对象有实现接口,并且没有强制开启cglib代理时默认使用的是JDK代理,也就是JdkDynamicAopProxy类。

也就是说,最后将调用的其实是new JdkDynamicAopProxy(config).getProxy(),结合Jdk动态代理底层源码的内容,可以预想到有2个需要特别关注的方法。getProxyinvoke方法

// JdkDynamicAopProxy.java
    @Override
    public Object getProxy(@Nullable ClassLoader classLoader) {
        if (logger.isTraceEnabled()) {
            logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
        }
        // 获取代理接口
        Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
        // 判断接口是否又hashCode和equals方法
        findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
        // 使用JDK代理(classLoader, 接口, 当前JdkDynamicAopProxy对象:用于回调invoke和target对象方法)
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }
// 上述代码
Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);

// 第一篇[Jdk动态代理底层源码]中学习的代码是一模一样的
return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);

可以看出,其实每个知识点都是关联在一起的,ProxyFactory作为Spring AOP的核心,使用的也是我们学习过的Jdk动态代理来实现的。结合第一篇Jdk动态代理底层源码的内容,最最重要的便是getProxyinvoke方法,下一节我们将进行JdkDynamicAopProxygetProxyinvoke方法的源码剖析

你可能感兴趣的:(Spring AOP ProxyFactory)