最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

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

配置類,開啟 AOP 的注解 @EnableAspectJAutoProxy

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

切面類

@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)類

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過程

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

@EnableAspectJAutoProxy 注解源碼,使用 @Import 注解,向 Spring 容器中導(dǎo)入 AspectJAutoProxyRegistrar 類,而 AspectJAutoProxyRegistrar 類實(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 的原理一樣,都是通過實(shí)現(xiàn) ImportBeanDefinitionRegistrar 接口, Mybatis 的實(shí)現(xiàn)類是 MapperScannerRegistrar ,而 AOP 的實(shí)現(xiàn)類是 AspectJAutoProxyRegistrar 。

// Mybatis

class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar

// AOP

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar

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

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

在這里插入圖片描述

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

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

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

二、AOP源碼分析

1. AspectJAutoProxyRegistrar類

來看一下 AspectJAutoProxyRegistrar 類中實(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中注冊一個(gè)beanName為org.springframework.aop.config.internalAutoProxyCreator的BeanDefinition
    registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
    return beanDefinition;
}

在這里插入圖片描述

在這里插入圖片描述

2. internalAutoProxyCreator類

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

在這里插入圖片描述

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

在這里插入圖片描述

在這里插入圖片描述

3. BeanPostProcessor方法執(zhí)行

我們要來看一下 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類此方法中
        // AnnotationAwareAspectJAutoProxyCreator的父類AbstractAutoProxyCreator實(shí)現(xiàn)了此方法
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}

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

在這里插入圖片描述

下面來分析下源碼:

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è)判斷很重要,可以通過配置文件進(jìn)行配置,來決定采用什么動(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)文章

  • Java中值類型和引用類型詳解

    Java中值類型和引用類型詳解

    大家好,本篇文章主要講的是Java中值類型和引用類型詳解,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽
    2022-01-01
  • Java 8 Stream 的終極技巧——Collectors 功能與操作方法詳解

    Java 8 Stream 的終極技巧——Collectors 功能與操作方法詳解

    這篇文章主要介紹了Java 8 Stream Collectors 功能與操作方法,結(jié)合實(shí)例形式詳細(xì)分析了Java 8 Stream Collectors 功能、操作方法及相關(guān)注意事項(xiàng),需要的朋友可以參考下
    2020-05-05
  • JDBC連接Mysql的5種方式實(shí)例總結(jié)

    JDBC連接Mysql的5種方式實(shí)例總結(jié)

    JDBC是Java DataBase Connectivity技術(shù)的簡稱,是一種可用于執(zhí)行 SQL語句的Java API,下面這篇文章主要給大家介紹了關(guān)于JDBC連接Mysql的5種方式,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-04-04
  • Spring Security認(rèn)證機(jī)制源碼層探究

    Spring Security認(rèn)證機(jī)制源碼層探究

    SpringSecurity是基于Filter實(shí)現(xiàn)認(rèn)證和授權(quán),底層通過FilterChainProxy代理去調(diào)用各種Filter(Filter鏈),F(xiàn)ilter通過調(diào)用AuthenticationManager完成認(rèn)證 ,通過調(diào)用AccessDecisionManager完成授權(quán)
    2023-03-03
  • 詳解Java虛擬機(jī)管理的內(nèi)存運(yùn)行時(shí)數(shù)據(jù)區(qū)域

    詳解Java虛擬機(jī)管理的內(nèi)存運(yùn)行時(shí)數(shù)據(jù)區(qū)域

    這篇文章主要介紹了詳解Java虛擬機(jī)管理的內(nèi)存運(yùn)行時(shí)數(shù)據(jù)區(qū)域的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • 詳解SpringCloudGateway內(nèi)存泄漏問題

    詳解SpringCloudGateway內(nèi)存泄漏問題

    這篇文章主要介紹了詳解SpringCloudGateway內(nèi)存泄漏問題,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • Spring IOC和DI實(shí)現(xiàn)原理及實(shí)例解析

    Spring IOC和DI實(shí)現(xiàn)原理及實(shí)例解析

    這篇文章主要介紹了Spring IOC和DI實(shí)現(xiàn)原理及實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-06-06
  • mybatis簡介與配置_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    mybatis簡介與配置_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    這篇文章主要介紹了mybatis簡介與配置,介紹了MyBatis+Spring+MySql簡單配置,有興趣的可以了解一下
    2017-09-09
  • ZooKeeper集群操作及集群Master選舉搭建啟動(dòng)

    ZooKeeper集群操作及集群Master選舉搭建啟動(dòng)

    這篇文章主要為大家介紹了ZooKeeper集群操作及集群Master選舉搭的建啟動(dòng)詳解,<BR>有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • MyBatis元素resultMap介紹及使用詳解

    MyBatis元素resultMap介紹及使用詳解

    這篇文章主要介紹了MyBatis元素resultMap介紹及使用,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06

最新評(píng)論

青田县| 三明市| 洞口县| 黔西县| 泗阳县| 交口县| 辽宁省| 永靖县| 肥乡县| 浪卡子县| 嘉祥县| 普格县| 临沭县| 抚顺县| 巧家县| 安多县| 长垣县| 沛县| 基隆市| 加查县| 弋阳县| 牙克石市| 九江市| 铁岭县| 梁山县| 云龙县| 枝江市| 册亨县| 松阳县| 修武县| 南宁市| 巫溪县| 凤城市| 岳西县| 德清县| 石门县| 湘潭市| 庆城县| 阳高县| 河津市| 丰城市|