Spring專題: 3. Spring AOP動態(tài)代理的原理

先上代碼,比如我使用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對象,關(guān)鍵點就在這里。
當一個對象被SpringAOP代理,那么當使用getBean獲取到的并不是對象本身,而是一個代理對象。

那么之前的文章bean的生命周期中,這個代理的過程是在哪一步進行的呢
createBeanInstance
populateBean
initlizeBean
其實發(fā)生在initlizeBean,在其中會執(zhí)行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;
        }
    }

執(zhí)行之后,返回的就是一個代理對象(代理對象包含一個Advisor數(shù)組,一個目標對象)

總結(jié)一下,Spring AOP動態(tài)代理的執(zhí)行過程如下
1.生成代理對象,初始化攔截器鏈(這發(fā)生在bean的生命周期initlizeBean中,生成是通過AopProxy接口,有兩個實現(xiàn)類Cglib2AopProxy,JdkDynamicAopProxy)
2.代碼中調(diào)用bean的某個方法的時候,實際上是通過代理對象調(diào)用的。調(diào)用時會獲取攔截器鏈,逐個進行匹配執(zhí)行(切面邏輯),最終通過反射的方法調(diào)用目標對象方法。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容