java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > AOP动态代理源码

Spring中的AOP动态代理源码详解

作者:止步前行

这篇文章主要介绍了Spring中的AOP动态代理源码详解,AOP即面向切面编程也称面向方面编程,它是面向对象编程OOP的一种补充,目前已成为一种比较成熟的编程方式,本文就其源码进行解析,需要的朋友可以参考下

一、Spring启动流程再分析

配置类,开启 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 ... ");
    }
}

启动类

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

对于 Import 的处理过程,可以看一下源码分析第四篇,包扫描中处理 @Import 注解部分。

@EnableAspectJAutoProxy 注解源码,使用 @Import 注解,向 Spring 容器中导入 AspectJAutoProxyRegistrar 类,而 AspectJAutoProxyRegistrar 类实现 ImportBeanDefinitionRegistrar 接口。

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

AOP 的原理和 Mybatis 的原理一样,都是通过实现 ImportBeanDefinitionRegistrar 接口, Mybatis 的实现类是 MapperScannerRegistrar ,而 AOP 的实现类是 AspectJAutoProxyRegistrar 。

// Mybatis

class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar

// AOP

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar

2. 执行Import导入类

在 parser.parse(candidates); 这行代码里完成了对 @Import 注解的导入工作,并对实现 ImportBeanDefinitionRegistrar 接口的类完成了实例化,并把已经创建好的实列放到了 ConfigurationClass 类的属性 importBeanDefinitionRegistrars 中,可以看下面断点图。

在这里插入图片描述

this.reader.loadBeanDefinitions() 这个方法中完成了对 ImportBeanDefinitionRegistrar 接口方法的调用。

下面就来看一下 AspectJAutoProxyRegistrar 类中实现 ImportBeanDefinitionRegistrar 接口的方法了。

AOP 的入口就在这里!!!!

二、AOP源码分析

1. AspectJAutoProxyRegistrar类

来看一下 AspectJAutoProxyRegistrar 类中实现 ImportBeanDefinitionRegistrar 接口方法。

该方法的作用就是往 Spring 容器中添加一个 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中注册一个beanName为org.springframework.aop.config.internalAutoProxyCreator的BeanDefinition
    registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
    return beanDefinition;
}

在这里插入图片描述

在这里插入图片描述

2. internalAutoProxyCreator类

再观察一下 internalAutoProxyCreator ,它的实现类是 org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator

在这里插入图片描述

经过 refresh() 方法中的 registerBeanPostProcessors() 方法, BeanPostProcessor 就已经实例化了,并且添加到了 beanFactory 工厂中的 beanPostProcessors 属性中。

在这里插入图片描述

在这里插入图片描述

3. BeanPostProcessor方法执行

我们要来看一下 BeanPostProcessor 的执行时机,在 populateBean() 属性赋值之后的 initializeBean() 方法中,进行了 Bean后置处理器 方法的调用。

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    // 权限检查
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            invokeAwareMethods(beanName, bean);
            return null;
        }, getAccessControlContext());
    } else {
        // 执行setBeanName/setBeanFactory赋值
        invokeAwareMethods(beanName, bean);
    }
    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        // 调用BeanPostProcessor接口中的postProcessBeforeInitialization()方法
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }
    try {
        // 执行自定义的init-method方法
        invokeInitMethods(beanName, wrappedBean, mbd);
    } catch (Throwable ex) {
       // 抛异常代码略
    }
    if (mbd == null || !mbd.isSynthetic()) {
        // 调用BeanPostProcessor接口中的postProcessAfterInitialization()方法
        // AOP代理就在AnnotationAwareAspectJAutoProxyCreator类此方法中
        // AnnotationAwareAspectJAutoProxyCreator的父类AbstractAutoProxyCreator实现了此方法
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}

上面这个 AnnotationAwareAspectJAutoProxyCreator 类中的 postProcessAfterInitialization() 方法执行过后, XService 实例就变成了 Cglib 代理对象了。

在这里插入图片描述

下面来分析下源码:

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);
        // 创建代理对象
        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 {
    // 这个判断很重要,可以通过配置文件进行配置,来决定采用什么动态代理
    if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
        Class<?> targetClass = config.getTargetClass();
        if (targetClass == null) {
			// 抛异常略
        }
        if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
            // 创建JDK动态代理
            return new JdkDynamicAopProxy(config);
        }
        // 创建Cglib动态代理
        return new ObjenesisCglibAopProxy(config);
    }
    else {
        return new JdkDynamicAopProxy(config);
    }
}

三、小结

AOP的原理和Mybatis的原理一样,都是利用了Spring中@Import导入ImportBeanDefinitionRegistrar这个扩展点。

先往容器中添加一个BeanDefinition,然后再适当的时机进行方法的调用。

到此这篇关于Spring中的AOP动态代理源码详解的文章就介绍到这了,更多相关AOP动态代理源码内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文