名词介绍
- JoinPoint:需要增强的方法
- PointCut:能够被一个正则表达式匹配到的一组JoinPoint
- Advice:增强方法
- Aspect/Advisor:PointCut + Advice
- Proxy:代理,方法被增强的类
类结构图
基于注解开启AOP
@Component
/*
* 开启注解AOP
* 替代了:<aop:aspectj-autoproxy/>
* */
@EnableAspectJAutoProxy(proxyTargetClass = false,exposeProxy = true)
public class EnableAspectJAutoProxyBean {
}
跟源码
在 Spring5 源码阅读笔记(1.4.2.5)initializeBean(beanName, exposedObject, mbd) 中有一个方法 applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName),跟进去
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
跟 postProcessAfterInitialization:
这个 AbstractAutoProxyCreator 就是用来处理AOP的。跟进去:
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
跟 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;
}
//重要程度:5 创建当前bean的代理,如果这个bean有advice的话 见3.1
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
//如果有切面,则生成该bean的代理
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//把被代理对象bean实例封装到SingletonTargetSource对象中 见3.2
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;
}