一,aop 术语
1.切面Aspect: Aspect 声明类似于 Java 中的类声明,在 Aspect 中会包含着一些切入点Pointcut 以及对切入点进行相应的操作的通知Advice。
2.连接点Joint point:表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等,它自身还可以嵌套其它连接点jointpoint。
简单说:就是spring允许你是通知(Advice)的地方
3.切入点Pointcut:表示一组连接点jointpoint,用于筛选连接点,这些连接点或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的操作处理通知Advice将要发生的地方。
4.通知Advice:Advice 定义了在切入点pointcut 里面定义的程序点具体要做的操作和处理,它通过 before、after 和 around 来区别是在每个切入点之前、之后还是代替执行的代码。
5.目标对象Target:代理的目标对象,即切面要被应用到的目标对象。
6.织入Weave:指将切面应用到目标对象,并导致代理对象创建的过程。
二,Spring AOP 创建代理对象的入口方法分析
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
@Override
/** bean 初始化后置处理方法 */
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
// 如果需要,为 bean 生成代理对象
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
/*
* 如果是基础设施类(Pointcut、Advice、Advisor 等接口的实现类),或是应该跳过的类,
* 则不应该生成代理,此时直接返回 bean
*/
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
// 将 键值对放入缓存中,供上面的 if 分支使用
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 为目标 bean 查找合适的通知器
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
/*
* 若 specificInterceptors != null,即 specificInterceptors != DO_NOT_PROXY,
* 则为 bean 生成代理对象,否则直接返回 bean
*/
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());
/*
* 返回代理对象,此时 IOC 容器输入 bean,得到 proxy。此时,
* beanName 对应的 bean 是代理对象,而非原始的 bean
*/
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
// specificInterceptors = null,直接返回 bean
return bean;
}
总结:
1.若 bean 是 AOP 基础设施类型,则直接返回
2.为 bean 查找合适的通知器
3.如果通知器数组不为空,则为 bean 生成代理对象,并返回该对象
4.若数组为空,则返回原始 bean
三,选择合适的通知器
在向目标 bean 中织入通知之前,我们先要为 bean 筛选出合适的通知器(通知器持有通知)。AspectJ 表达式进行匹配。那下面我们就来看一下使用 AspectJ 表达式筛选通知器的过程,如下(AspectJ 表达式:https://www.cnblogs.com/kanyun/p/7818529.html)
protected Object[] getAdvicesAndAdvisorsForBean(Class> beanClass, String beanName, TargetSource targetSource) {
// 查找合适的通知器
List advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List findEligibleAdvisors(Class> beanClass, String beanName) {
// 查找所有的通知器
List candidateAdvisors = findCandidateAdvisors();
/*
* 筛选可应用在 beanClass 上的 Advisor,通过 ClassFilter 和 MethodMatcher
* 对目标类和方法进行匹配
*/
List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 拓展操作
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
四:查找通知器
Spring 提供了两种配置 AOP 的方式,
1.通过 XML 进行配置,
2是注解。
对于两种配置方式,Spring 的处理逻辑是不同的,
XML 类型的配置如下,注解的配置略
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {
//...
@Override
protected List findCandidateAdvisors() {
// 调用父类方法从容器中查找所有的通知器
List advisors = super.findCandidateAdvisors();
// 解析 @Aspect 注解,并构建通知器
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
return advisors;
}
//...
}
AnnotationAwareAspectJAutoProxyCreator 覆写了父类的方法 findCandidateAdvisors,并增加了一步操作,即解析 @Aspect 注解,并构建成通知器。下面我先来分析一下父类中的 findCandidateAdvisors 方法的逻辑,然后再来分析 buildAspectJAdvisors 方法逻的辑。
findCandidateAdvisors 方法
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {
private BeanFactoryAdvisorRetrievalHelper advisorRetrievalHelper;
//...
protected List findCandidateAdvisors() {
return this.advisorRetrievalHelper.findAdvisorBeans();
}
//...
}
AbstractAdvisorAutoProxyCreator 中的 findCandidateAdvisors 是个空壳方法,
所有逻辑封装在了一个 BeanFactoryAdvisorRetrievalHelper 的 findAdvisorBeans 方法中。
BeanFactoryAdvisorRetrievalHelper 可以理解为从 bean 容器中获取 Advisor 的帮助类,
findAdvisorBeans 则可理解为查找 Advisor 类型的 bean。
findAdvisorBeans 方法做下面事情
1,从容器中查找所有类型为 Advisor 的 bean 对应的名称
2,遍历 advisorNames,并从容器中获取对应的 bean
public List findAdvisorBeans() {
String[] advisorNames = null;
synchronized (this) {
// cachedAdvisorBeanNames 是 advisor 名称的缓存
advisorNames = this.cachedAdvisorBeanNames;
/*
* 如果 cachedAdvisorBeanNames 为空,这里到容器中查找,
* 并设置缓存,后续直接使用缓存即可
*/
if (advisorNames == null) {
// 从容器中查找 Advisor 类型 bean 的名称
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
// 设置缓存
this.cachedAdvisorBeanNames = advisorNames;
}
}
if (advisorNames.length == 0) {
return new LinkedList();
}
List advisors = new LinkedList();
// 遍历 advisorNames
for (String name : advisorNames) {
if (isEligibleBean(name)) {
// 忽略正在创建中的 advisor bean
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isDebugEnabled()) {
logger.debug("Skipping currently created advisor '" + name + "'");
}
}
else {
try {
/*
* 调用 getBean 方法从容器中获取名称为 name 的 bean,
* 并将 bean 添加到 advisors 中
*/
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
catch (BeanCreationException ex) {
Throwable rootCause = ex.getMostSpecificCause();
if (rootCause instanceof BeanCurrentlyInCreationException) {
BeanCreationException bce = (BeanCreationException) rootCause;
if (this.beanFactory.isCurrentlyInCreation(bce.getBeanName())) {
if (logger.isDebugEnabled()) {
logger.debug("Skipping advisor '" + name +
"' with dependency on currently created bean: " + ex.getMessage());
}
continue;
}
}
throw ex;
}
}
}
}
return advisors;
}
@Aspect 注解,并构建通知器(buildAspectJAdvisors方法)
1,获取容器中所有 bean 的名称(beanName)
2,遍历上一步获取到的 bean 名称数组,并获取当前 beanName 对应的 bean 类型(beanType)
3,根据 beanType 判断当前 bean 是否是一个的 Aspect 注解类,若不是则不做任何处理
4,调用 advisorFactory.getAdvisors 获取通知器
public List buildAspectJAdvisors() {
List aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List advisors = new LinkedList();
aspectNames = new LinkedList();
// 从容器中获取所有 bean 的名称
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
// 遍历 beanNames
for (String beanName : beanNames) {
if (!isEligibleBean(beanName)) {
continue;
}
// 根据 beanName 获取 bean 的类型
Class> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
// 检测 beanType 是否包含 Aspect 注解
if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
// 获取通知器
List classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
}
else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
else {
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException("Bean with name '" + beanName +
"' is a singleton, but aspect instantiation model is not singleton");
}
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
List advisors = new LinkedList();
for (String aspectName : aspectNames) {
List cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
}
else {
MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
分析:advisorFactory.getAdvisors(factory)
public List getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
// 获取 aspectClass 和 aspectName
Class> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
validate(aspectClass);
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List advisors = new LinkedList();
// getAdvisorMethods 用于返回不包含 @Pointcut 注解的方法
for (Method method : getAdvisorMethods(aspectClass)) {
// 为每个方法分别调用 getAdvisor 方法
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
// If it's a per target aspect, emit the dummy instantiating aspect.
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}
// Find introduction fields.
for (Field field : aspectClass.getDeclaredFields()) {
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
// 获取切点实现类
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
// 创建 Advisor 实现类
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
如上,getAdvisor 方法包含两个主要步骤,
1.一个是获取 AspectJ 表达式切点,
2、创建 Advisor 实现类。
获取 AspectJ 表达式切点
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class> candidateAspectClass) {
// 获取方法上的 AspectJ 相关注解,包括 @Before,@After 等
AspectJAnnotation> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// 创建一个 AspectJExpressionPointcut 对象
AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class>[0]);
// 设置切点表达式
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
ajexp.setBeanFactory(this.beanFactory);
return ajexp;
}
protected static AspectJAnnotation> findAspectJAnnotationOnMethod(Method method) {
// classesToLookFor 中的元素是大家熟悉的
Class>[] classesToLookFor = new Class>[] {
Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};
for (Class> c : classesToLookFor) {
// 查找注解
AspectJAnnotation> foundAnnotation = findAnnotation(method, (Class) c);
if (foundAnnotation != null) {
return foundAnnotation;
}
}
return null;
}