Spring源码解析(9)——AOP

AOP使用

首先创建一个TestAopBean

public class TestAopBean {

	private String testStr = "javaGuiji";

	public String getTestStr () {
		return testStr;
	}

	public void setTestStr(String testStr){
		this.testStr = testStr;
	}

	public void testAop(){

		System.out.println("test aop guiji");

	}
}

然后创建一个AspectJTest

@Aspect
public class AspectJTest {

	@Pointcut("execution(* *.testAop(..))")
	public void test(){

	}

	@Before("test()")
	public void beforeTest(){
		System.out.println("before test");
	}

	@After("test()")
	public void afterTest(){
		System.out.println("after test");
	}

	@Around("test()")
	public Object arountTest(ProceedingJoinPoint point){

		System.out.println(" around test start");

		Object o = null;

		try {
			o = point.proceed();
		} catch (Throwable throwable) {

		}

		System.out.println(" around test end");

		return o;
	}
}

再创建一个测试类AopTest

public class AopTest {

	public static void main(String[] args) {

		ApplicationContext beanFactory = new ClassPathXmlApplicationContext("BeanFactoryTest.xml");

		TestAopBean testAopBean = (TestAopBean) beanFactory.getBean("testAopBean");

		testAopBean.testAop();
	}

}

最后在配置文件中配置TestAopBean和AspectJTest,再加上aop的配置。

	<bean id="testAopBean" class="com.guiji.bean.TestAopBean">

	</bean>

	<bean id="aspectJTest" class="com.guiji.bean.AspectJTest">

	</bean>

	<aop:aspectj-autoproxy />

执行测试类之后打印出

around test start
before test
test aop guiji
around test end
after test

我们可以看到在执行
testAopBean.testAop();
这个方法前打印了
around test start
before test
执行完
testAopBean.testAop();
后,打印了
around test end
after test
接下来我们就分析AOP是如何实现这一功能的。

分析源码实现

1、解析配置文件

我们在配置文件中添加了<aop:aspectj-autoproxy />之后,Spring就能支持AOP了。<aop:aspectj-autoproxy />是一个自定义配置,那么Spring一定在某个地方注册了解析这个配置的解析器。我们在idea中全局搜索一下aspectj-autoproxy。找到下面代码。

	@Override
	public void init() {
		// In 2.0 XSD as well as in 2.1 XSD.
		registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
		//注册了一个AspectJAutoProxyBeanDefinitionParser解析器
		registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
		registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());

		// Only in 2.0 XSD: moved to context namespace as of 2.1
		registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
	}

这里面注册了一个
AspectJAutoProxyBeanDefinitionParser。
再看到
AspectJAutoProxyBeanDefinitionParser
里面parse方法做了什么事情。

@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
	//注册AspectJAnnotationAutoProxyCreator
	AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
	extendBeanDefinition(element, parserContext);
	return null;
}

在parse方法中,向Spring中注册了一个
AnnotationAwareAspectJAutoProxyCreator,
注册这个类有什么用呢?
我们看到这个类的结构图。
AnnotationAwareAspectJAutoProxyCreator结构图
我们看到这个类实现了
InstantiationAwareBeanPostProcessor

BeanPostProcessor
接口,实现了这两个接口Spring就会在创建bean的时候去执行一些操作。现在我们回到之前创建bean的代码。

在创建bean的逻辑中有一段这样的代码。
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
我们进入到resolveBeforeInstantiation这个方法里面。

	@Nullable
	protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
		Object bean = null;
		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
			//hasInstantiationAwareBeanPostProcessors是否存在InstantiationAwareBeanPostProcessors这个类
			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
				Class<?> targetType = determineTargetType(beanName, mbd);
				if (targetType != null) {
					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
					if (bean != null) {
						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
					}
				}
			}
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
	}

这段代码就是判断是否存在类型为
InstantiationAwareBeanPostProcessors的类。
而上面我们注册的
AnnotationAwareAspectJAutoProxyCreator
实现了
InstantiationAwareBeanPostProcessors
所以是存在的,就会去执行
AnnotationAwareAspectJAutoProxyCreator
这个类的
postProcessBeforeInstantiation方法。

在创建bean的逻辑中还存在
exposedObject = initializeBean(beanName, exposedObject, mbd);
这一段代码。
我们看看initializeBean这个方法做了什么。

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			//执行所有BeanPostProcessor的postProcessBeforeInitialization方法
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}
		invokeInitMethods(beanName, wrappedBean, mbd);
		//执行所有BeanPostProcessor的postProcessAfterInitialization方法
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
		return wrappedBean;
	}

这段代码就是在实例化bean前,去获取所有的BeanPostProcessor,然后调用BeanPostProcessor的postProcessBeforeInitialization方法,在实例化bean后调用postProcessAfterInitialization方法,上面注册的AnnotationAwareAspectJAutoProxyCreator实现了BeanPostProcessor这个接口,所以在bean实例化的时候AnnotationAwareAspectJAutoProxyCreator的
postProcessBeforeInitialization方法

postProcessAfterInitialization方法
会被调用。

通过上面分析我们知道了,配置了<aop:aspectj-autoproxy />标签,就会注册一个AspectJAutoProxyBeanDefinitionParser解析器,而这个解析器执行解析方法的时候,会注册一个实现了InstantiationAwareBeanPostProcessor接口和BeanPostProcessor接口的AnnotationAwareAspectJAutoProxyCreator,注册了这个bean之后,在后续bean创建的过程中都会去执行AnnotationAwareAspectJAutoProxyCreator的postProcessBeforeInstantiation、
postProcessAfterInstantiation方法

postProcessBeforeInitialization、
postProcessAfterInitialization方法。
其中postProcessAfterInstantiation和postProcessBeforeInitialization里面是没有什么逻辑的,下面我们主要看postProcessBeforeInstantiation和postProcessAfterInitialization
这两个方法。

2、postProcessBeforeInstantiation

postProcessBeforeInitialization这个方法在AbstractAutoProxyCreator这个类里面,AnnotationAwareAspectJAutoProxyCreator是继承了AbstractAutoProxyCreator

@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
	Object cacheKey = getCacheKey(beanClass, beanName);
	//beanName不为空或者不在targetSourcedBeans中
	if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
		//advisedBeans里保存的是不需要代理的类的cacheKey
		if (this.advisedBeans.containsKey(cacheKey)) {
			return null;
		}
		//判断是否是不需要代理的类,是的话将这个类放入advisedBeans中
		if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return null;
		}
	}

	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;
}

isInfrastructureClass方法主要是判断传入的类是不是Advice/Pointcut/Advisor/AopInfrastructureBean的类或子类和里面是否有Aspect注解,满足其中一个就会返回true,表示这个类不需要被代理。

	@Override
protected boolean isInfrastructureClass(Class<?> beanClass) {
	return (
			//判断beanClass是不是Advice/Pointcut/Advisor/AopInfrastructureBean的类或子类
			super.isInfrastructureClass(beanClass) ||
			//判断beanClass里面有没有Aspect注解
			(this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass)));
}
protected boolean isInfrastructureClass(Class<?> beanClass) {
	boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
			Pointcut.class.isAssignableFrom(beanClass) ||
			Advisor.class.isAssignableFrom(beanClass) ||
			AopInfrastructureBean.class.isAssignableFrom(beanClass);
	if (retVal && logger.isTraceEnabled()) {
		logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
	}
	return retVal;
}

shouldSkip方法主要是获取所有增强器,如果存在AspectJPointcutAdvisor类型的增强器,并且增强器切面名称与当前beanName相等,则会返回true。

	@Override
	protected boolean shouldSkip(Class<?> beanClass, String beanName) {
		// 找到所有增强器
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		//如果存在类型为AspectJPointcutAdvisor的增强器名称与beanName一致返回true
		for (Advisor advisor : candidateAdvisors) {
			if (advisor instanceof AspectJPointcutAdvisor &&
					((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
				return true;
			}
		}
		return super.shouldSkip(beanClass, beanName);
	}

3、postProcessAfterInitialization

postProcessBeforeInitialization这个方法也是在AbstractAutoProxyCreator这个类里面

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
	if (bean != null) {
		//根据class和beanName构造一个缓存key
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		if (this.earlyProxyReferences.remove(cacheKey) != bean) {
			//满足被代理的条件,则为这个bean创建一个代理对象
			return wrapIfNecessary(bean, beanName, cacheKey);
		}
	}
	return bean;
}
wrapIfNecessary
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		//这个判断条件之前我们已经分析过了,就是判断beanName不为空并且在targetSourcedBeans中
		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;
		}
		//获取适用于当前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;
		}
		//走到这步说明这个bean不符合代理条件,设置为不需要代理,返回当前bean
		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

这段代码的主要逻辑为:
1、如果beanName不为空且存在于targetSourcedBeans中,则直接返回该bean。
2、如果当前bean被标记过不需要代理则直接返回该bean。
3、如果当前bean是内部基础设置类Class 或 配置了该bean不需要代理,则直接返回bean。
4、获取适用于当前bean的增强Advisor。
5、如果增强不为null,则为该bean创建代理对象,并返回结果,否则标记该bean为不适合代理,并返回改bean。
这里面获取增强(getAdvicesAndAdvisorsForBean)和创建代理(createProxy)是我们比较关心的两个逻辑。后续我们再继续分析这两块逻辑中具体做了什么。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值