欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring中的AOP動(dòng)態(tài)代理源碼詳解

 更新時(shí)間:2023年09月18日 10:58:42   作者:止步前行  
這篇文章主要介紹了Spring中的AOP動(dòng)態(tài)代理源碼詳解,AOP即面向切面編程也稱(chēng)面向方面編程,它是面向?qū)ο缶幊蘋(píng)OP的一種補(bǔ)充,目前已成為一種比較成熟的編程方式,本文就其源碼進(jìn)行解析,需要的朋友可以參考下

一、Spring啟動(dòng)流程再分析

配置類(lèi),開(kāi)啟 AOP 的注解 @EnableAspectJAutoProxy

@Configuration
@ComponentScan("com.scorpios")
@EnableAspectJAutoProxy
public class AppConfig {
}

切面類(lèi)

@Aspect
@Component
public class AspectJScorpios {
    @Pointcut("execution(* com.scorpios.service..*.*(..))")
    public void pointCut(){
    }
    @Before("pointCut()")
    public void before(){
        System.out.println(" proxy before ... ");
    }
}

啟動(dòng)類(lèi)

public static void main( String[] args )
{
    AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
    ac.register(AppConfig.class);
    ac.refresh();
    XService xService = (XService) ac.getBean("XService");
    xService.print();
}

1. 處理Import過(guò)程

對(duì)于 Import 的處理過(guò)程,可以看一下源碼分析第四篇,包掃描中處理 @Import 注解部分。

@EnableAspectJAutoProxy 注解源碼,使用 @Import 注解,向 Spring 容器中導(dǎo)入 AspectJAutoProxyRegistrar 類(lèi),而 AspectJAutoProxyRegistrar 類(lèi)實(shí)現(xiàn) ImportBeanDefinitionRegistrar 接口。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
	boolean proxyTargetClass() default false;
	boolean exposeProxy() default false;
}

AOP 的原理和 Mybatis 的原理一樣,都是通過(guò)實(shí)現(xiàn) ImportBeanDefinitionRegistrar 接口, Mybatis 的實(shí)現(xiàn)類(lèi)是 MapperScannerRegistrar ,而 AOP 的實(shí)現(xiàn)類(lèi)是 AspectJAutoProxyRegistrar 。

// Mybatis

class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar

// AOP

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar

2. 執(zhí)行Import導(dǎo)入類(lèi)

在 parser.parse(candidates); 這行代碼里完成了對(duì) @Import 注解的導(dǎo)入工作,并對(duì)實(shí)現(xiàn) ImportBeanDefinitionRegistrar 接口的類(lèi)完成了實(shí)例化,并把已經(jīng)創(chuàng)建好的實(shí)列放到了 ConfigurationClass 類(lèi)的屬性 importBeanDefinitionRegistrars 中,可以看下面斷點(diǎn)圖。

在這里插入圖片描述

this.reader.loadBeanDefinitions() 這個(gè)方法中完成了對(duì) ImportBeanDefinitionRegistrar 接口方法的調(diào)用。

下面就來(lái)看一下 AspectJAutoProxyRegistrar 類(lèi)中實(shí)現(xiàn) ImportBeanDefinitionRegistrar 接口的方法了。

AOP 的入口就在這里?。。?!

二、AOP源碼分析

1. AspectJAutoProxyRegistrar類(lèi)

來(lái)看一下 AspectJAutoProxyRegistrar 類(lèi)中實(shí)現(xiàn) ImportBeanDefinitionRegistrar 接口方法。

該方法的作用就是往 Spring 容器中添加一個(gè) BeanDefinition , beanName 為 org.springframework.aop.config.internalAutoProxyCreator 。

beanClass 為 AnnotationAwareAspectJAutoProxyCreator.class 。

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(
        AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        // 核心方法
        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
        AnnotationAttributes enableAspectJAutoProxy =
            AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
        if (enableAspectJAutoProxy != null) {
            if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }
            if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
                AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
            }
        }
    }
}
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
    return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
    BeanDefinitionRegistry registry, @Nullable Object source) {
    return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
private static BeanDefinition registerOrEscalateApcAsRequired(
    Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
    if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
        BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
        if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
            int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
            int requiredPriority = findPriorityForClass(cls);
            if (currentPriority < requiredPriority) {
                apcDefinition.setBeanClassName(cls.getName());
            }
        }
        return null;
    }
    // 此處的的beanClass為AnnotationAwareAspectJAutoProxyCreator.class
    RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
    beanDefinition.setSource(source);
    beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
    beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    // 往beanDefinitionMap中注冊(cè)一個(gè)beanName為org.springframework.aop.config.internalAutoProxyCreator的BeanDefinition
    registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
    return beanDefinition;
}

在這里插入圖片描述

在這里插入圖片描述

2. internalAutoProxyCreator類(lèi)

再觀察一下 internalAutoProxyCreator ,它的實(shí)現(xiàn)類(lèi)是 org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator

在這里插入圖片描述

經(jīng)過(guò) refresh() 方法中的 registerBeanPostProcessors() 方法, BeanPostProcessor 就已經(jīng)實(shí)例化了,并且添加到了 beanFactory 工廠中的 beanPostProcessors 屬性中。

在這里插入圖片描述

在這里插入圖片描述

3. BeanPostProcessor方法執(zhí)行

我們要來(lái)看一下 BeanPostProcessor 的執(zhí)行時(shí)機(jī),在 populateBean() 屬性賦值之后的 initializeBean() 方法中,進(jìn)行了 Bean后置處理器 方法的調(diào)用。

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    // 權(quán)限檢查
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            invokeAwareMethods(beanName, bean);
            return null;
        }, getAccessControlContext());
    } else {
        // 執(zhí)行setBeanName/setBeanFactory賦值
        invokeAwareMethods(beanName, bean);
    }
    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        // 調(diào)用BeanPostProcessor接口中的postProcessBeforeInitialization()方法
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }
    try {
        // 執(zhí)行自定義的init-method方法
        invokeInitMethods(beanName, wrappedBean, mbd);
    } catch (Throwable ex) {
       // 拋異常代碼略
    }
    if (mbd == null || !mbd.isSynthetic()) {
        // 調(diào)用BeanPostProcessor接口中的postProcessAfterInitialization()方法
        // AOP代理就在AnnotationAwareAspectJAutoProxyCreator類(lèi)此方法中
        // AnnotationAwareAspectJAutoProxyCreator的父類(lèi)AbstractAutoProxyCreator實(shí)現(xiàn)了此方法
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}

上面這個(gè) AnnotationAwareAspectJAutoProxyCreator 類(lèi)中的 postProcessAfterInitialization() 方法執(zhí)行過(guò)后, XService 實(shí)例就變成了 Cglib 代理對(duì)象了。

在這里插入圖片描述

下面來(lái)分析下源碼:

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        // 創(chuàng)建代理對(duì)象
        Object proxy = createProxy(
            bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
                             @Nullable Object[] specificInterceptors, TargetSource targetSource) {
    if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
        AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
    }
    ProxyFactory proxyFactory = new ProxyFactory();
    proxyFactory.copyFrom(this);
    if (!proxyFactory.isProxyTargetClass()) {
        if (shouldProxyTargetClass(beanClass, beanName)) {
            proxyFactory.setProxyTargetClass(true);
        }
        else {
            evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }
    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    proxyFactory.addAdvisors(advisors);
    proxyFactory.setTargetSource(targetSource);
    customizeProxyFactory(proxyFactory);
    proxyFactory.setFrozen(this.freezeProxy);
    if (advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }
    return proxyFactory.getProxy(getProxyClassLoader());
}
public Object getProxy(@Nullable ClassLoader classLoader) {
    return createAopProxy().getProxy(classLoader);
}
protected final synchronized AopProxy createAopProxy() {
    if (!this.active) {
        activate();
    }
    return getAopProxyFactory().createAopProxy(this);
}
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    // 這個(gè)判斷很重要,可以通過(guò)配置文件進(jìn)行配置,來(lái)決定采用什么動(dòng)態(tài)代理
    if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
        Class<?> targetClass = config.getTargetClass();
        if (targetClass == null) {
			// 拋異常略
        }
        if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
            // 創(chuàng)建JDK動(dòng)態(tài)代理
            return new JdkDynamicAopProxy(config);
        }
        // 創(chuàng)建Cglib動(dòng)態(tài)代理
        return new ObjenesisCglibAopProxy(config);
    }
    else {
        return new JdkDynamicAopProxy(config);
    }
}

三、小結(jié)

AOP的原理和Mybatis的原理一樣,都是利用了Spring中@Import導(dǎo)入ImportBeanDefinitionRegistrar這個(gè)擴(kuò)展點(diǎn)。

先往容器中添加一個(gè)BeanDefinition,然后再適當(dāng)?shù)臅r(shí)機(jī)進(jìn)行方法的調(diào)用。

到此這篇關(guān)于Spring中的AOP動(dòng)態(tài)代理源碼詳解的文章就介紹到這了,更多相關(guān)AOP動(dòng)態(tài)代理源碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 使用IDEA對(duì)SpringBoot應(yīng)用進(jìn)行遠(yuǎn)程調(diào)試方式

    使用IDEA對(duì)SpringBoot應(yīng)用進(jìn)行遠(yuǎn)程調(diào)試方式

    文章介紹了如何在IDEA中對(duì)部署在服務(wù)器上的SpringBoot應(yīng)用進(jìn)行遠(yuǎn)程調(diào)試,通過(guò)配置遠(yuǎn)程調(diào)試端口和啟動(dòng)參數(shù),本地IDEA可以設(shè)置斷點(diǎn)并進(jìn)行調(diào)試
    2025-02-02
  • java json 省市級(jí)聯(lián)實(shí)例代碼

    java json 省市級(jí)聯(lián)實(shí)例代碼

    這篇文章介紹了java json 省市級(jí)聯(lián)實(shí)例代碼,有需要的朋友可以參考一下
    2013-09-09
  • SwiftUI中級(jí)List如何添加新內(nèi)容(2020年教程)

    SwiftUI中級(jí)List如何添加新內(nèi)容(2020年教程)

    這篇文章主要介紹了SwiftUI中級(jí)List如何添加新內(nèi)容,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • spring+hibernate 兩種整合方式配置文件的方法

    spring+hibernate 兩種整合方式配置文件的方法

    本篇文章主要介紹了spring+hibernate 兩種整合方式配置文件的方法,主要有兩種方式 1、注解方式 2、xml方式實(shí)現(xiàn),有興趣的可以了解一下。
    2017-04-04
  • SpringBoot核心@SpringBootApplication使用介紹

    SpringBoot核心@SpringBootApplication使用介紹

    這篇文章主要介紹了SpringBoot核心@SpringBootApplication的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • java程序員如何編寫(xiě)更好的單元測(cè)試的7個(gè)技巧

    java程序員如何編寫(xiě)更好的單元測(cè)試的7個(gè)技巧

    測(cè)試是開(kāi)發(fā)的一個(gè)非常重要的方面,可以在很大程度上決定一個(gè)應(yīng)用程序的命運(yùn)。良好的測(cè)試可以在早期捕獲導(dǎo)致應(yīng)用程序崩潰的問(wèn)題,但較差的測(cè)試往往總是導(dǎo)致故障和停機(jī)。本文主要介紹java程序員編寫(xiě)更好的單元測(cè)試的7個(gè)技巧。下面跟著小編一起來(lái)看下吧
    2017-03-03
  • Java實(shí)現(xiàn)自定義中文排序的方法機(jī)注意事項(xiàng)

    Java實(shí)現(xiàn)自定義中文排序的方法機(jī)注意事項(xiàng)

    在Java中,中文排序通常涉及到使用Collator類(lèi)來(lái)處理字符串的比較,確保根據(jù)漢字的拼音順序進(jìn)行排序,本文給大家介紹了Java實(shí)現(xiàn)自定義中文排序的方法機(jī)注意事項(xiàng),并有相關(guān)的代碼示例供大家參考,需要的朋友可以參考下
    2024-10-10
  • Java利用for循環(huán)輸出空心菱形的實(shí)例代碼

    Java利用for循環(huán)輸出空心菱形的實(shí)例代碼

    這篇文章主要介紹了Java利用for循環(huán)輸出空心菱形的實(shí)例代碼,需要的朋友可以參考下
    2014-02-02
  • 深入解析Java中反射中的invoke()方法

    深入解析Java中反射中的invoke()方法

    最近復(fù)習(xí)了一下Java反射的使用,正好了解一下Java中反射中的invoke()方法,稍微整理精簡(jiǎn)一下做下分享,感興趣的可以了解一下
    2021-06-06
  • SpringBoot 指標(biāo)監(jiān)控actuator的專(zhuān)題

    SpringBoot 指標(biāo)監(jiān)控actuator的專(zhuān)題

    未來(lái)每一個(gè)微服務(wù)在云上部署以后,我們都需要對(duì)其進(jìn)行監(jiān)控、追蹤、審計(jì)、控制等。SpringBoot就抽取了Actuator場(chǎng)景,使得我們每個(gè)微服務(wù)快速引用即可獲得生產(chǎn)級(jí)別的應(yīng)用監(jiān)控、審計(jì)等功能,通讀本篇對(duì)大家的學(xué)習(xí)或工作具有一定的價(jià)值,需要的朋友可以參考下
    2021-11-11

最新評(píng)論