Spring源码分析:AOP分析(一)

 2019-10-17 21:51  阅读(873)
文章分类:Spring boot

前言

原文发布于: http://blog.ztgreat.cn/article/60

Spring 的两大核心,一是IOC,我们之前已经学习过,而另一个则是大名鼎鼎的 AOP,AOP的具体概念我就不介绍了,我们今天重点是要从源码层面去看看 spring 的 AOP 是如何实现的。

在Spring AOP实现中,使用的核心技术是动态代理,生成代理类有两种策略:jdk动态代理和cglib动态代理。

下面简要的谈一谈这两种代理

JDK动态代理

jdk 代理是基于接口实现的,最好的学习方式当然是看源码,因此这里我们可以将生成的代理类导出,再通过反编译查看代码,看看里面是怎么回事。

定义一个UserService接口:

public interface UserService {

        void add();

    }

实现类UserServiceImpl

public class UserServiceImpl implements UserService {

        public void add() {
            System.out.println("--------------------add----------------------");
        }
    }

编写自己的InvocationHandler:

public class MyInvocationHandler implements InvocationHandler {

        private Object target;
        public MyInvocationHandler(Object target) {
            super();
            this.target = target;
        }
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("-----------------begin "+method.getName()+"-----------------");
            Object result = method.invoke(target, args);
            System.out.println("-----------------end "+method.getName()+"-----------------");
            return result;
        }
        public Object getProxy(){
            return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), target.getClass().getInterfaces(), this);
        }

    }

将代理类导出:

public class JdkProxyTest {

        public static void main(String[] args) {

            //生成的代理类保存到磁盘
            System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
            UserService service = new UserServiceImpl();
            MyInvocationHandler handler = new MyInvocationHandler(service);
            UserService proxy = (UserService) handler.getProxy();
            proxy.add();
        }

    }

现在JDK动态代理已经完成了,现在我们来看看生成的代理类反编译结果:

public final class $Proxy0 extends Proxy implements UserService {
        //省略部分代码
        private static Method m3;
        public $Proxy0(InvocationHandler h) throws  {
            super(h);
        }
        //代理类的add 方法
        public final void add() throws  {
            try {
                //调用 InvocationHandler 的invoke方法
                super.h.invoke(this, m3, (Object[])null);
            } catch (RuntimeException | Error var2) {
                throw var2;
            } catch (Throwable var3) {
                throw new UndeclaredThrowableException(var3);
            }
        }

        static {
            try {

                m3 = Class.forName("com.study.spring.proxy.jdk.UserService").getMethod("add", new Class[0]);
                //省略部分代码
            } catch (NoSuchMethodException var2) {
                throw new NoSuchMethodError(var2.getMessage());
            } catch (ClassNotFoundException var3) {
                throw new NoClassDefFoundError(var3.getMessage());
            }
        }
    }

通过代码很容易就明白了,JDK动态代理是使用接口生成新的实现类,实现类里面则委托给InvocationHandler,InvocationHandler里面则调用被代理的类方法。

CGLIB 动态代理

同JDK代理一样,通过代码来理解

编写方法拦截器:

public class CglibProxy implements MethodInterceptor {
        private Enhancer enhancer = new Enhancer();
        public Object getProxy(Class clazz) {
            enhancer.setSuperclass(clazz);
            enhancer.setCallback( this);
            return enhancer.create();
        }

        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            System.out.println("-----------------begin "+method.getName()+"-----------------");
            Object result = proxy.invokeSuper(obj, args);
            System.out.println("-----------------end "+method.getName()+"-----------------");
            return result;
        }
    }

导出代理类:

public class CglibProxyTest {

        public static void main(String[] args){
            //生成代理类到本地
            System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "com/study/spring/proxy/cglib");
            UserServiceImpl service = new UserServiceImpl();
            CglibProxy cp = new CglibProxy();
            UserService proxy = (UserService) cp.getProxy(service.getClass());
            proxy.add();
        }
    }

反编译代理类,由于代码有点长,因此删减了一部分:

public class UserServiceImpl$$EnhancerByCGLIB$$d166e24d extends UserServiceImpl implements Factory {
        private boolean CGLIB$BOUND;
        public static Object CGLIB$FACTORY_DATA;
        private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
        private static final Callback[] CGLIB$STATIC_CALLBACKS;
        private MethodInterceptor CGLIB$CALLBACK_0;
        private static Object CGLIB$CALLBACK_FILTER;
        private static final Method CGLIB$add$0$Method;
        private static final MethodProxy CGLIB$add$0$Proxy;

        final void CGLIB$add$0() {
            super.add();
        }

        public final void add() {
            MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
            if(this.CGLIB$CALLBACK_0 == null) {
                CGLIB$BIND_CALLBACKS(this);
                var10000 = this.CGLIB$CALLBACK_0;
            }

            if(var10000 != null) {
                var10000.intercept(this, CGLIB$add$0$Method, CGLIB$emptyArgs, CGLIB$add$0$Proxy);
            } else {
                super.add();
            }
        }
        public UserServiceImpl$$EnhancerByCGLIB$$d166e24d() {
            CGLIB$BIND_CALLBACKS(this);
        }

        public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {
            CGLIB$THREAD_CALLBACKS.set(var0);
        }

        public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {
            CGLIB$STATIC_CALLBACKS = var0;
        }

        private static final void CGLIB$BIND_CALLBACKS(Object var0) {
            UserServiceImpl$$EnhancerByCGLIB$$d166e24d var1 = (UserServiceImpl$$EnhancerByCGLIB$$d166e24d)var0;
            if(!var1.CGLIB$BOUND) {
                var1.CGLIB$BOUND = true;
                Object var10000 = CGLIB$THREAD_CALLBACKS.get();
                if(var10000 == null) {
                    var10000 = CGLIB$STATIC_CALLBACKS;
                    if(CGLIB$STATIC_CALLBACKS == null) {
                        return;
                    }
                }

                var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
            }

        }

        public Object newInstance(Callback[] var1) {
            CGLIB$SET_THREAD_CALLBACKS(var1);
            UserServiceImpl$$EnhancerByCGLIB$$d166e24d var10000 = new UserServiceImpl$$EnhancerByCGLIB$$d166e24d();
            CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
            return var10000;
        }

        public Object newInstance(Callback var1) {
            CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
            UserServiceImpl$$EnhancerByCGLIB$$d166e24d var10000 = new UserServiceImpl$$EnhancerByCGLIB$$d166e24d();
            CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
            return var10000;
        }

        public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
            CGLIB$SET_THREAD_CALLBACKS(var3);
            UserServiceImpl$$EnhancerByCGLIB$$d166e24d var10000 = new UserServiceImpl$$EnhancerByCGLIB$$d166e24d;
            switch(var1.length) {
            case 0:
                var10000.<init>();
                CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
                return var10000;
            default:
                throw new IllegalArgumentException("Constructor not found");
            }
        }

        public Callback getCallback(int var1) {
            CGLIB$BIND_CALLBACKS(this);
            MethodInterceptor var10000;
            switch(var1) {
            case 0:
                var10000 = this.CGLIB$CALLBACK_0;
                break;
            default:
                var10000 = null;
            }

            return var10000;
        }

        public void setCallback(int var1, Callback var2) {
            switch(var1) {
            case 0:
                this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;
            default:
            }
        }

        public Callback[] getCallbacks() {
            CGLIB$BIND_CALLBACKS(this);
            return new Callback[]{this.CGLIB$CALLBACK_0};
        }

        public void setCallbacks(Callback[] var1) {
            this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0];
        }

        static {
            CGLIB$STATICHOOK1();
        }
    }

通过代码我们知道,Cglib是通过直接继承被代理类

从代理类里面可知道对于原来的add函数,代理类里面对应了两个函数分别是add 和CGLIB$add$0
其中后者是在方法拦截器里面调用的,前者则是我们使用代理类时候调用的函数。当我们代码调用add时候,会具体调用到方法拦截器的intercept方法。

整体上JDK代理和CGLIB代理思想上都是差不多的,jdk基于接口,cglib基于继承(因此方法不能被final修饰)。

深入 AOP 源码实现

阅读源码很好用的一个方法就是跑代码来调试,因为自己一行一行地看的话,比较枯燥,而且难免会漏掉一些东西,为了更方便的调试代码,这里我们采用xml配置方式,简要的实现aop功能。

同样使用上面的 UserService 和UserServiceImpl类

创建一个Advice,这里实现 MethodBeforeAdvice接口:

public class BeforeAdvice implements MethodBeforeAdvice {

        public void before(Method method, Object[] objects, @Nullable Object o) throws Throwable{
            System.out.println(o.getClass() + ":"+method.getName()+" 方法准备执行");
        }
    }

xml:

<bean id="userService" class="com.study.spring.aop.UserServiceImpl"/>
        <!--advice-->
        <bean id="beforeAdvice" class="com.study.spring.aop.BeforeAdvice" />
        <bean id="userServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean" >
            <!--代理接口类-->
            <property name="proxyInterfaces" value="com.study.spring.aop.UserService"/>
            <!--代理实现类-->
            <property name="target"  ref="userService"/>

            <!--走CGLIB代理-->
            <!--<property name="proxyTargetClass"  value="true"/>-->

            <!--配置拦截器,这里可以配置advice,advisor,interceptor-->
            <property name="interceptorNames">
                <!--引用我们beforeAdvice-->
                <list><value>beforeAdvice</value></list>
            </property>
    </bean>

测试代码:

public void TestAOP(){

            ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");

            ProxyFactoryBean abcProxy = (ProxyFactoryBean) context.getBean("&userServiceProxy");

            UserService userService= (UserService) abcProxy.getObject();

            userService.add();

            //实际获取的是被FactoryBean 包装后的bean
            userService = (UserService) context.getBean("userServiceProxy");

            userService.add();

    }

运行结果这里就不展示了,在调用add 方法前,都会先执行我们的BeforeAdvice,AOP生效。

上面的代码中又涉及到了FactoryBean,这个我们在前面讲IOC的时候已经说过了,这里当然也就不在说了,不知道的朋友,可以自行再去看看。

ProxyFactoryBean

代码很简单,配置也很简单,核心代码其实也就是ProxyFactoryBean,它是一个FactoryBean,那么在getBean的时候,会调用该FactoryBean的getObject 方法,因此 ProxyFactoryBean 的 getObject 方法就是我们的入口了。

getObject

public Object getObject() throws BeansException {
        initializeAdvisorChain();
        if (isSingleton()) {
            return getSingletonInstance();
        }
        else {
            if (this.targetName == null) {
                logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
                            "Enable prototype proxies by setting the 'targetName' property.");
            }
            return newPrototypeInstance();
        }
    }

该方法很重要,首先初始化Advice链,然后获取单例,这里返回的就是我们最初看到的代理bean。这里的初始化Advice链的重要作用就是将其连接起来,基本实现就是循环我们在配置文件中(interceptorNames)配置的拦截器,按照链表的方式连接起来。

initializeAdvisorChain

/**
    * Create the advisor (interceptor) chain. Advisors that are sourced
    * from a BeanFactory will be refreshed each time a new prototype instance
    * is added. Interceptors added programmatically through the factory API
    * are unaffected by such changes.
    */
    private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
        if (this.advisorChainInitialized) {
            return;
        }
        if (!ObjectUtils.isEmpty(this.interceptorNames)) {
            if (this.beanFactory == null) {
                throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
                            "- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
            }

            // Globals can't be last unless we specified a targetSource using the property...
        if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&
                this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
                throw new AopConfigException("Target required after globals");
            }
        for (String name : this.interceptorNames) {
            if (name.endsWith(GLOBAL_SUFFIX)) {
                if (!(this.beanFactory instanceof ListableBeanFactory)) {
                    throw new AopConfigException(
                                    "Can only use global advisors or interceptors with a ListableBeanFactory");
                }
                addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
                                name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
            }
            else {
                Object advice;
                if (this.singleton || this.beanFactory.isSingleton(name)) {
                    //根据name 获取bean
                    advice = this.beanFactory.getBean(name);
                }
                    else {
                        advice = new PrototypePlaceholderAdvisor(name);
                    }
                    addAdvisorOnChainCreation(advice, name);
                }
            }
        }

        this.advisorChainInitialized = true;
    }

代码比较简单,核心思想就是初始化我们配置的拦截器,里面会递归调用getBean 方法。

我们着重关注下面的方法 getSingletonInstance();

getSingletonInstance

private synchronized Object getSingletonInstance() {
        if (this.singletonInstance == null) {
            this.targetSource = freshTargetSource();
            if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
                // Rely on AOP infrastructure to tell us what interfaces to proxy.
                Class<?> targetClass = getTargetClass();
                if (targetClass == null) {
                    throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
                }
                setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
            }
            // Initialize the shared singleton instance.
            super.setFrozen(this.freezeProxy);
            this.singletonInstance = getProxy(createAopProxy());
        }
        return this.singletonInstance;
    }

该方法是同步方法,防止并发错误,因为有共享变量。首先返回一个包装过的目标对象,重要的一行是 getProxy(createAopProxy()),先创建AOP,再获取代理。我们先看 crateAopProxy。

protected final synchronized AopProxy createAopProxy() {
        if (!this.active) {
            activate();
        }
        return getAopProxyFactory().createAopProxy(this);
    }

该方法返回一个AopProxy 类型的实例,我们看看该接口:

20191017100212\_1.png

这是该接口的继承图,分别是 JdkDynamicAopProxy 动态代理和 CglibAopProxy 代理。

我们继续看 createAopProxy 方法,该方法主要逻辑是创建一个AOP 工厂,默认工厂是 DefaultAopProxyFactory

DefaultAopProxyFactory

public ProxyCreatorSupport() {
       this.aopProxyFactory = new DefaultAopProxyFactory();
    }

该类的 createAopProxy 方法则根据 ProxyFactoryBean 的一些属性来决定创建哪种代理:

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        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);
            }
            return new ObjenesisCglibAopProxy(config);
        }
        else {
            return new JdkDynamicAopProxy(config);
        }
    }

到这里,我们知道 createAopProxy 方法有可能返回 JdkDynamicAopProxy 实例,也有可能返回 ObjenesisCglibAopProxy 实例,这里总结一下:

如果被代理的目标类实现了一个或多个自定义的接口,那么就会使用 JDK 动态代理,如果没有实现任何接口,会使用 CGLIB 实现代理,如果设置了 proxy-target-class=“true”,那么通常都会使用 CGLIB。

JDK 动态代理基于接口,所以只有接口中的方法会被增强,而 CGLIB 基于类继承,需要注意就是如果方法使用了 final 修饰,或者是 private 方法,是不能被增强的

我们分别来看下两个 AopProxy 实现类的 getProxy(classLoader) 实现。

JdkDynamicAopProxy

getProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
        Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
        findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }

java.lang.reflect.Proxy.newProxyInstance(…) 方法需要三个参数,第一个是 ClassLoader,第二个参数代表需要实现哪些接口,第三个参数最重要,是 InvocationHandler 实例,我们看到这里传了 this,因为 JdkDynamicAopProxy 本身实现了 InvocationHandler 接口。

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
        ...
    }

InvocationHandler 只有一个方法,当生成的代理类对外提供服务的时候,都会回到这个方法中:

invoke
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        MethodInvocation invocation;
        Object oldProxy = null;
        boolean setProxyContext = false;

        TargetSource targetSource = this.advised.targetSource;
        Object target = null;

        try {
            if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
                // The target does not implement the equals(Object) method itself.
                // 代理equals 方法
                return equals(args[0]);
            }
            else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
                // The target does not implement the hashCode() method itself.
                // 代理hashCode 方法
                return hashCode();
            }
            else if (method.getDeclaringClass() == DecoratingProxy.class) {
                // There is only getDecoratedClass() declared -> dispatch to proxy config.
                return AopProxyUtils.ultimateTargetClass(this.advised);
            }
            else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                        method.getDeclaringClass().isAssignableFrom(Advised.class)) {
                // Service invocations on ProxyConfig with the proxy config...
                return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
            }

            Object retVal;
            // 如果设置了 exposeProxy,那么将 proxy 放到 ThreadLocal 中
            if (this.advised.exposeProxy) {
                // Make invocation available if necessary.
                oldProxy = AopContext.setCurrentProxy(proxy);
                setProxyContext = true;
            }

            // Get as late as possible to minimize the time we "own" the target,
            // in case it comes from a pool.
            target = targetSource.getTarget();
            Class<?> targetClass = (target != null ? target.getClass() : null);

            // 创建一个 chain,包含所有要执行的 advice
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

            if (chain.isEmpty()) {
                // chain 是空的,说明不需要被增强
                Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
            }
            else {
                // We need to create a method invocation...
                invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                //执行增强,并调用方法
                retVal = invocation.proceed();
            }

            //返回值检查
            Class<?> returnType = method.getReturnType();
            if (retVal != null && retVal == target &&
                        returnType != Object.class && returnType.isInstance(proxy) &&
                        !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
                // Special case: it returned "this" and the return type of the method
                // is type-compatible. Note that we can't help if the target sets
                // a reference to itself in another returned object.
                retVal = proxy;
            }
            else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
                throw new AopInvocationException(
                            "Null return value from advice does not match primitive return type for: " + method);
            }
            return retVal;
        }
        finally {
            if (target != null && !targetSource.isStatic()) {
                // Must have come from TargetSource.
                targetSource.releaseTarget(target);
            }
            if (setProxyContext) {
                // Restore old proxy.
                AopContext.setCurrentProxy(oldProxy);
            }
        }
    }

核心逻辑不算复杂,重点分析创建advice chain,然后调用方法代码那里(44行~57行),可以进行断点调试,观察一下执行流程,这里就不继续追下去了,感兴趣的读者自己去深入探索下,不是很难。

说完了 JDK 动态代理 JdkDynamicAopProxy,我们再来看一下 CGLIB 的代理实现 ObjenesisCglibAopProxy。

ObjenesisCglibAopProxy 继承了 CglibAopProxy,而 CglibAopProxy 继承了 AopProxy。

CglibAopProxy

在前面我们知道得到AopProxy后,会调用getProxy 方法,因此这里我们直接就来看看该方法。

getProxy
public Object getProxy(@Nullable ClassLoader classLoader) {

        try {
            Class<?> rootClass = this.advised.getTargetClass();

            Class<?> proxySuperClass = rootClass;
            if (ClassUtils.isCglibProxyClass(rootClass)) {
                proxySuperClass = rootClass.getSuperclass();
                Class<?>[] additionalInterfaces = rootClass.getInterfaces();
                for (Class<?> additionalInterface : additionalInterfaces) {
                    this.advised.addInterface(additionalInterface);
                }
            }

            // Validate the class, writing log messages as necessary.
            validateClassIfNecessary(proxySuperClass, classLoader);

            // Configure CGLIB Enhancer...
            Enhancer enhancer = createEnhancer();
            if (classLoader != null) {
                enhancer.setClassLoader(classLoader);
                if (classLoader instanceof SmartClassLoader &&
                            ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
                    enhancer.setUseCache(false);
                }
            }
            enhancer.setSuperclass(proxySuperClass);
            enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
            enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
            enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));

            Callback[] callbacks = getCallbacks(rootClass);
            Class<?>[] types = new Class<?>[callbacks.length];
            for (int x = 0; x < types.length; x++) {
                types[x] = callbacks[x].getClass();
            }
            // fixedInterceptorMap only populated at this point, after getCallbacks call above
            enhancer.setCallbackFilter(new ProxyCallbackFilter(
                        this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
            enhancer.setCallbackTypes(types);

            // Generate the proxy class and create a proxy instance.
            return createProxyClassAndInstance(enhancer, callbacks);
        }
        catch (CodeGenerationException | IllegalArgumentException ex) {
            throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
                        ": Common causes of this problem include using a final class or a non-visible class",
                        ex);
        }
        catch (Throwable ex) {
            // TargetSource.getTarget() failed
            throw new AopConfigException("Unexpected AOP exception", ex);
        }
    }

从上面代码中,可以看到对CGLIB的使用,比如对Enhancer对象的配置,以及通过Enhancer 对象生成代理对象的过程。在这个生成代理对象的过程中,需要注意的是对Enhancer对象callback回调的设置,正是这些回调封装了Spring AOP的实现,就像前面介绍的JDK的Proxy对象的invoke回调方法一样。在Enhancer的callback回调设置中,实际上是通过设置DynamicAdvisedInterceptor拦截器来完成AOP功能的。

private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
        // Parameters used for optimization choices...
        boolean exposeProxy = this.advised.isExposeProxy();
        boolean isFrozen = this.advised.isFrozen();
        boolean isStatic = this.advised.getTargetSource().isStatic();

        // Choose an "aop" interceptor (used for AOP calls).
        Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
        ...
    }

DynamicAdvisedInterceptor 参数中的 this.advised 是一个AdvisedSupport实例,这个是在创建AOpProxy的时候传入的。

现在切入点在 DynamicAdvisedInterceptor 类了

DynamicAdvisedInterceptor

核心方法便是intercept 方法了,类似invoke 方法。

public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        Object oldProxy = null;
        boolean setProxyContext = false;
        Object target = null;
        TargetSource targetSource = this.advised.getTargetSource();
        try {
            if (this.advised.exposeProxy) {
                // Make invocation available if necessary.
                oldProxy = AopContext.setCurrentProxy(proxy);
                setProxyContext = true;
            }
            // Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
            target = targetSource.getTarget();
            Class<?> targetClass = (target != null ? target.getClass() : null);
            //回去拦截器链
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
            Object retVal;
            // Check whether we only have one InvokerInterceptor: that is,
            // no real advice, but just reflective invocation of the target.
            if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
                //如果拦截器为空,则直接进行方法调用
                Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                retVal = methodProxy.invoke(target, argsToUse);
            }
            else {
                //拦截器调用,方法调用
                retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
            }
            retVal = processReturnType(proxy, target, method, retVal);
            return retVal;
        }
        finally {
            if (target != null && !targetSource.isStatic()) {
                targetSource.releaseTarget(target);
            }
            if (setProxyContext) {
                // Restore old proxy.
                AopContext.setCurrentProxy(oldProxy);
            }
        }
    }

方法逻辑和JdkDynamicAopProxy 中的invoke 方法是差不多的,这里就不多说了。

总结

以ProxyFactoryBean为例,通过简单的配置,对Spring AOP的基本实现和工作流程进行了简单的梳理,通过ProxyFactoryBean 得到AopProxy对象。

通过使用AopProxy对象封装target目标对象之后,ProxyFactoryBean的getObject方法得到的对象就不是一个普通的Java对象了,而是一个AoppProxy代理对象。在ProxyFactoryBean中配置的target目标对象,这时已经不会让应用直接调用其方法实现,而是作为AOP实现的一部分。对target目标对象的方法调用会首先被AopProxy代理对象拦截,对于不同的AopProxy代理对象生成方法,会使用不同的拦截回调入口。例如,对于JDK的AopProxy代理对象,使用是InvocationHandler的invoke回调入口;而对于CGLIB的AopProxy代理对象,使用的是设置好的callback回调,在这些callback 回调中,对于AOP实现,是通过DynamicAdvisedInterceptor 来完成的,而DynamicAdvisedInterceptor的回调入口是intercept方法。

参考

Spring 技术内幕

JDK动态代理代理与Cglib代理原理探究


来源:[]()

点赞(0)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> Spring源码分析:AOP分析(一)

相关推荐