美文网首页Spring专题
Spring专题: 3. Spring AOP动态代理的原理

Spring专题: 3. Spring AOP动态代理的原理

作者: 北交吴志炜 | 来源:发表于2019-01-05 19:32 被阅读0次

    先上代码,比如我使用aspectj风格的注解,定义了一个针对naiveWaiter的切面逻辑

    @Aspect
    public class TestAspect {
       
        /**
         * 访问连接点对象
         */
        @Around("execution(* greetTo(..)) && target(com.brianway.learning.spring.aop.aspectj.NaiveWaiter)")
        public void joinPointAccess(ProceedingJoinPoint pjp) throws Throwable {
            System.out.println("------joinPointAccess-------");
            System.out.println("args[0]:" + pjp.getArgs()[0]);
            System.out.println("target:" + pjp.getTarget());
            System.out.println("signature:" + pjp.getSignature());
            System.out.println("this:" + pjp.getThis());
    
            pjp.proceed();
            System.out.println("-------joinPointAccess-------");
        }
    

    测试类如下

    @Test
        public void testJoinPoint() {
            String configPath = "com/brianway/learning/spring/aop/aspectj/beans-advanced.xml";
            ApplicationContext context = new ClassPathXmlApplicationContext(configPath);
            Waiter naiveWaiter = (Waiter) context.getBean("naiveWaiter");
            naiveWaiter.greetTo("Brian");
        }
    

    debug看一下这个naiveWaiter对象到底是什么

    462722787.jpg
    可以看到这个naiveWaiter对象其实是一个EnhancerBySpringCglib
    并不是一个普通的NaiveWaiter对象,关键点就在这里。
    当一个对象被SpringAOP代理,那么当使用getBean获取到的并不是对象本身,而是一个代理对象。

    那么之前的文章bean的生命周期中,这个代理的过程是在哪一步进行的呢
    createBeanInstance
    populateBean
    initlizeBean
    其实发生在initlizeBean,在其中会执行BeanProcessor.postProcessAfterInitialization
    具体就是AbstractAutoProxyCreator类的postProcessAfterInitialization 方法

    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
            if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
                return bean;
            } else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
                return bean;
            } else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
                Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
                if (specificInterceptors != DO_NOT_PROXY) {
                    this.advisedBeans.put(cacheKey, Boolean.TRUE);
                    Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
                    this.proxyTypes.put(cacheKey, proxy.getClass());
                    return proxy;
                } else {
                    this.advisedBeans.put(cacheKey, Boolean.FALSE);
                    return bean;
                }
            } else {
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return bean;
            }
        }
    

    执行之后,返回的就是一个代理对象(代理对象包含一个Advisor数组,一个目标对象)

    总结一下,Spring AOP动态代理的执行过程如下
    1.生成代理对象,初始化拦截器链(这发生在bean的生命周期initlizeBean中,生成是通过AopProxy接口,有两个实现类Cglib2AopProxy,JdkDynamicAopProxy)
    2.代码中调用bean的某个方法的时候,实际上是通过代理对象调用的。调用时会获取拦截器链,逐个进行匹配执行(切面逻辑),最终通过反射的方法调用目标对象方法。

    相关文章

      网友评论

        本文标题:Spring专题: 3. Spring AOP动态代理的原理

        本文链接:https://www.haomeiwen.com/subject/pcjdrqtx.html