• 小话 Spring AOP 源码


    在上篇 Spring AOP 简单使用 中简单介绍了 AOP 相关概念和使用,这篇将要按照注解驱动的 Spring 来进行 AOP 源码的学习分享,欢迎阅读斧正。

    通过下面的源码分析,会了解到

    1. Spring AOP 有两种实现方式,一个是 JDK 自带的,另外就是 CGLib 了。
    2. BeanPostProcessor 是怎么将代理融入到 Bean 的生命周期的

    @EnableAspectJAutoProxy

    在 Spring 中我们可以通过 @EnableAspectJAutoProxy 来驱动整个 AOP 模块,代码如下:

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import(AspectJAutoProxyRegistrar.class)
    public @interface EnableAspectJAutoProxy {
    
    	/**
    	 * 是否开启类代理(CGLib)
    	 */
    	boolean proxyTargetClass() default false;
    
    	/**
    	 * 是否暴露代理对象
    	 */
    	boolean exposeProxy() default false;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在上述代码中我们看到 @Import(AspectJAutoProxyRegistrar.class) 此行代码,接着分析。

    AspectJAutoProxyRegistrar

    class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
    
    	/**
    	 * Register, escalate, and configure the AspectJ auto proxy creator based on the value
    	 * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
    	 * {@code @Configuration} class.
    	 */
    	@Override
    	public void registerBeanDefinitions(
    			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    		// ① 注册一个 AnnotationAwareAspectJAutoProxyCreator
    		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
    		// ② 获取注解 EnableAspectJAutoProxy 的相关信息
    		AnnotationAttributes enableAspectJAutoProxy =
    				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
    		if (enableAspectJAutoProxy != null) {
    			if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
    				// 开启类代理
    				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
    			}
    			if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
    				// 需要暴露对象
    				AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
    			}
    		}
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    ① 处的代码重点是 AnnotationAwareAspectJAutoProxyCreator 这个类

    	@Nullable
    	public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
    			BeanDefinitionRegistry registry, @Nullable Object source) {
    
    		return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    AnnotationAwareAspectJAutoProxyCreator

    详细代码就不贴了,直接看类图:
    在这里插入图片描述
    看了 AnnotationAwareAspectJAutoProxyCreator 类图后,你会发现它实现了 BeanPostProcessor 接口以及 InstantiationAwareBeanPostProcessor 接口:

    public interface BeanPostProcessor {
    	@Nullable
    	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    		return bean;
    	}
    	@Nullable
    	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    		return bean;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
    
    	@Nullable
    	default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
    		return null;
    	}
    
    	default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
    		return true;
    	}
    
    	// 省略无关代码
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    AbstractAutoProxyCreator

    上述代码中有四个和 Bean 生命周期密切相关的两个方法,咱们看下如何重写的。

    生命周期博客敬请期待

    public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
    
    	// 省略无关代码
    	
    	@Override
    	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
    		Object cacheKey = getCacheKey(beanClass, beanName);
    
    		if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
    			if (this.advisedBeans.containsKey(cacheKey)) {
    				return null;
    			}
    			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
    				this.advisedBeans.put(cacheKey, Boolean.FALSE);
    				return null;
    			}
    		}
    
    		// Create proxy here if we have a custom TargetSource.
    		// Suppresses unnecessary default instantiation of the target bean:
    		// The TargetSource will handle target instances in a custom fashion.
    		TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
    		if (targetSource != null) {
    			if (StringUtils.hasLength(beanName)) {
    				this.targetSourcedBeans.add(beanName);
    			}
    			Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
    			Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
    			this.proxyTypes.put(cacheKey, proxy.getClass());
    			return proxy;
    		}
    
    		return null;
    	}
    
    	@Override
    	public boolean postProcessAfterInstantiation(Object bean, String beanName) {
    		return true;
    	}
    
    	@Override
    	public Object postProcessBeforeInitialization(Object bean, String beanName) {
    		return bean;
    	}
    
    	/**
    	 * Create a proxy with the configured interceptors if the bean is
    	 * identified as one to proxy by the subclass.
    	 * @see #getAdvicesAndAdvisorsForBean
    	 */
    	@Override
    	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;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    重点看下 wrapIfNecessary() 方法:

    	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;
    		}
    
    		// Create proxy if we have advice.
    		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;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    再来看下 createProxy() 方法:

    	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());
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    ProxyFactory

    再来看 getProxy() 方法:

    public Object getProxy(@Nullable ClassLoader classLoader) {
    		return createAopProxy().getProxy(classLoader);
    	}
    
    • 1
    • 2
    • 3

    其实是调用了 AopProxy#getProxy(@Nullable ClassLoader classLoader),咱们来看下具体实现:
    在这里插入图片描述

    CglibAopProxy

    class CglibAopProxy implements AopProxy, Serializable {
    	@Override
    	public Object getProxy(@Nullable ClassLoader classLoader) {
    		if (logger.isTraceEnabled()) {
    			logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
    		}
    
    		try {
    			Class<?> rootClass = this.advised.getTargetClass();
    			Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
    
    			Class<?> proxySuperClass = rootClass;
    			if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
    				proxySuperClass = rootClass.getSuperclass();
    				Class<?>[] additionalInterfaces = rootClass.getInterfaces();
    				for (Class<?> additionalInterface : additionalInterfaces) {
    					this.advised.addInterface(additionalInterface);
    				}
    			}
    
    			// Validate the class, writing log messages as necessary.
    			validateClassIfNecessary(proxySuperClass, classLoader);
    
    			// Configure CGLIB Enhancer...
    			Enhancer enhancer = createEnhancer();
    			if (classLoader != null) {
    				enhancer.setClassLoader(classLoader);
    				if (classLoader instanceof SmartClassLoader &&
    						((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
    					enhancer.setUseCache(false);
    				}
    			}
    			enhancer.setSuperclass(proxySuperClass);
    			enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
    			enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
    			enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
    
    			Callback[] callbacks = getCallbacks(rootClass);
    			Class<?>[] types = new Class<?>[callbacks.length];
    			for (int x = 0; x < types.length; x++) {
    				types[x] = callbacks[x].getClass();
    			}
    			// fixedInterceptorMap only populated at this point, after getCallbacks call above
    			enhancer.setCallbackFilter(new ProxyCallbackFilter(
    					this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
    			enhancer.setCallbackTypes(types);
    
    			// Generate the proxy class and create a proxy instance.
    			return createProxyClassAndInstance(enhancer, callbacks);
    		}
    		catch (CodeGenerationException | IllegalArgumentException ex) {
    			throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
    					": Common causes of this problem include using a final class or a non-visible class",
    					ex);
    		}
    		catch (Throwable ex) {
    			// TargetSource.getTarget() failed
    			throw new AopConfigException("Unexpected AOP exception", ex);
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    其中 Enhancer 这玩意就是重点,就先分析到这。

    JdkDynamicAopProxy

    final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
    	@Override
    	public Object getProxy(@Nullable ClassLoader classLoader) {
    		if (logger.isTraceEnabled()) {
    			logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
    		}
    		Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    看到了咱们熟悉的 Java 动态代理:Proxy.newProxyInstance(classLoader, proxiedInterfaces, this),就不再多做介绍。


  • 相关阅读:
    nginx服务中使用用户认证功能,对Web后台url进行用户验证【加一层认证】
    leetcode经典面试150题---2.移除元素
    JDBC学习
    Swagger2 介绍与集成
    【OFDM系列5】单输入单输出OFDM(SISO-OFDM)多径信道迫零(ZF)和最小均方误差(MMSE)均衡器原理和公式推导
    数学建模学习(91):快速非支配排序的遗传算法(NSGA-II)多目标寻优
    Jquary全屏滚动插件fullpage.js的使用
    java基础16
    【代码随想录】算法训练营 第五天 第三章 哈希表 Part 1
    含文档+PPT+源码等]精品基于Uniapp+SSM实现的新闻APP[包运行成功]计算机毕业设计安卓项目源码
  • 原文地址:https://blog.csdn.net/MrBaymax/article/details/126595573