Spring专题

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

2019-01-05  本文已影响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的某个方法的时候,实际上是通过代理对象调用的。调用时会获取拦截器链,逐个进行匹配执行(切面逻辑),最终通过反射的方法调用目标对象方法。

上一篇 下一篇

猜你喜欢

热点阅读