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,
注册这个类有什么用呢?
我们看到这个类的结构图。
我们看到这个类实现了
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)是我们比较关心的两个逻辑。后续我们再继续分析这两块逻辑中具体做了什么。