目录
一、概述
二、示例
三、Spring AOP如何进行初始化?
1.添加@EnableAspectJAutoProxy注解
2.IOC容器初始化,执行refresh()方法
3.执行registerBeanPostProcessor()
4.执行finishBeanFactoryInitialization(beanFactory)
4.1. 情况一:如果此时的bean是切面类(标注@Aspect)。
4.2. 情况二:此时的bean是需要被切的类(即@Pointcut("a.b.c")中a.b.c覆盖到的类)
四、Spring AOP是如何起作用的?
五、总结
AOP(Aspect-Oriented Programming) 面向切面编程。Spring Aop是Spring三大核心思想之一,其应用场景化非常多,比如日志、事务、安全、缓存等功能。分析Spring AOP之前,建议先提前了解下什么是spring容器和容器初始化,这样对以下的Spring AOP的分析更有帮助。 Spring AOP的原理,简单的说,可以从两个方面着手,即Spring AOP如何进行初始化?Spring AOP是如何起作用的?围绕这两点,我们展开分析,首先举个简单的例子,这样对分析更具有实质性,也更容易理解。
以下使用的spring Boot版本为:2.3.5.RELEASE
/**
* spring boot启动类
* 添加@EnableAspectJAutoProxy注解,它提供了spring aop初始化的核心功能
*/
@SpringBootApplication
@EnableAspectJAutoProxy
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
/**
* 切面类
**/
@Aspect
@Component
public class LogAspects {
//抽取公共的切入点表达式
@Pointcut("execution(public Integer com.micro.provider.service.UserService.*(..))")
public void pointCut(){};
@Before("pointCut()")
public void logStart(JoinPoint joinPoint){
Object[] args = joinPoint.getArgs();
System.out.println(""+joinPoint.getSignature().getName()+"运行。。。@Before:参数列表是:{"+ Arrays.asList(args)+"}");
}
@After("pointCut()")
public void logEnd(JoinPoint joinPoint){
System.out.println(""+joinPoint.getSignature().getName()+"结束。。。@After");
}
//JoinPoint一定要出现在参数表的第一位
@AfterReturning(value="pointCut()",returning="result")
public void logReturn(JoinPoint joinPoint,Object result){
System.out.println(""+joinPoint.getSignature().getName()+"正常返回。。。@AfterReturning:运行结果:{"+result+"}");
}
@AfterThrowing(value="pointCut()",throwing="exception")
public void logException(JoinPoint joinPoint,Exception exception){
System.out.println(""+joinPoint.getSignature().getName()+"异常。。。异常信息:{"+exception+"}");
}
}
/**
* 应用切面类的接口
*/
public interface UserService {
/**
* 加法运算
* @param x
* @param y
* @return
*/
Integer add(Integer x,Integer y);
}
/**
* 接口实现类
*/
@Service
public class UserServiceImpl implements UserService {
@Override
public Integer add(Integer x, Integer y) {
if(x==null||y==null){
throw new NullPointerException("参数不能为空");
}
return x+y;
}
}
/**
* 访问入口
*/
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@ResponseBody
@RequestMapping("/testaop")
public Integer testaop(Integer x,Integer y){
Integer result = userService.add(x, y);
return result;
}
}
访问http://localhost:8081/cloud-provider/user/testaop?x=1&&y=2之后,返回结果如下:
add运行。。。@Before:参数列表是:{[1, 2]}
add正常返回。。。@AfterReturning:运行结果:{3}
add结束。。。@After
可以看出切面类被应用到了,这个结果是怎么得出的呢,来我们具体分析下。
Spring AOP如何进行初始化,它的初始化步骤分为以下几点。
如上面的示例,在启动类添加@EnableAspectJAutoProxy注解,看下他的内部实现。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({AspectJAutoProxyRegistrar.class})
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
...
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
...
}
}
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, (Object)null);
}
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
private static BeanDefinition registerOrEscalateApcAsRequired(Class> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {
...
} else {
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", -2147483648);
beanDefinition.setRole(2);
registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition);
return beanDefinition;
}
}
其本质就是往bean定义注册表中注册AnnotationAwareAspectJAutoProxyCreator类,该类是个后置处理器,继承关系为AnnotationAwareAspectJAutoProxyCreator->AspectJAwareAdvisorAutoProxyCreator->AbstractAdvisorAutoProxyCreator->AbstractAutoProxyCreator->SmartInstantiationAwareBeanPostProcessor->InstantiationAwareBeanPostProcessor->BeanPostProcessor。
AbstractAutoProxyCreator里面实现了识别切面类、应用切面类以及创建代理对象的逻辑。
InstantiationAwareBeanPostProcessor是一个后置处理器,它的作用就是使IOC容器初始化的时候可以应用到AbstractAutoProxyCreator里面的逻辑,完成spring aop的初始化工作。
public void refresh() throws BeansException, IllegalStateException {
// 来个锁,不然 refresh() 还没结束,你又来个启动或销毁容器的操作,那不就乱套了嘛
synchronized (this.startupShutdownMonitor) {
// 准备工作,记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符
prepareRefresh();
// 这步比较关键,这步完成后,配置文件就会解析成一个个 Bean 定义,注册到 BeanFactory 中,
// 当然,这里说的 Bean 还没有初始化,只是配置信息都提取出来了,
// 注册也只是将这些信息都保存到了注册中心(说到底核心是一个 beanName-> beanDefinition 的 Map)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
// 这块待会会展开说
prepareBeanFactory(beanFactory);
try {
// 【这里需要知道 BeanFactoryPostProcessor 这个知识点,Bean 如果实现了此接口,
// 那么在容器初始化以后,Spring 会负责调用里面的 postProcessBeanFactory 方法。】
// 这里是提供给子类的扩展点,到这里的时候,所有的 Bean 都加载、注册完成了,但是都还没有初始化
// 具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事
postProcessBeanFactory(beanFactory);
// 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法
invokeBeanFactoryPostProcessors(beanFactory);
// 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
// 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
// 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
registerBeanPostProcessors(beanFactory);
// 初始化当前 ApplicationContext 的 MessageSource,国际化这里就不展开说了,不然没完没了了
initMessageSource();
// 初始化当前 ApplicationContext 的事件广播器,这里也不展开了
initApplicationEventMulticaster();
// 从方法名就可以知道,典型的模板方法(钩子方法),
// 具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
onRefresh();
// 注册事件监听器,监听器需要实现 ApplicationListener 接口。这也不是我们的重点,过
registerListeners();
// 重点,重点,重点
// 初始化所有的 singleton beans,并将它们放入Spring容器的缓存中(缓存底层为ConcurrentHashMap结构)
//(lazy-init 的除外)
finishBeanFactoryInitialization(beanFactory);
// 最后,广播事件,ApplicationContext 初始化完成
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
// 销毁已经初始化的 singleton 的 Beans,以免有些 bean 会一直占用资源
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// 把异常往外抛
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
这里我们重点关注与aop初始化关联的主要逻辑,registerBeanPostProcessor和finishBeanFactoryInitialization。
注册后置处理器(只是创建了这个对象:AnnotationAwareAspectJAutoProxyCreator)
循环实例化所有的未实例化的单例bean:
4.1.1. 实例化bean之前
->执行resolveBeforeInstantiation->InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
...
beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
if (beanInstance != null) {
return beanInstance;
}
...
}
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
Class> targetType = this.determineTargetType(beanName, mbd);
if (targetType != null) {
//主要进行AbstractAutoProxyCreator.postProcessBeforeInstantiation操作
bean = this.applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
//如果有返回对象(上面返回的是包含切面逻辑的该bean的代理对象),继续执行实例化后置通知方法
bean = this.applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = bean != null;
}
return bean;
}
public Object postProcessBeforeInstantiation(Class> beanClass, String beanName) {
Object cacheKey = this.getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
//advisedBeans用于存储不可代理的bean,如果包含直接返回
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
//判断当前bean是否可以被代理,然后存入advisedBeans
if (this.isInfrastructureClass(beanClass) || this.shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
//获取当前bean的TargetSource对象,如果不存在,则直接退出当前方法,否则从TargetSource中获取当前bean对象,并且判断是否需要将切面逻辑应用在当前bean上
TargetSource targetSource = this.getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
// 获取能够应用当前bean的切面逻辑
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
//创建包含切面逻辑的该bean的代理对象
Object proxy = this.createProxy(beanClass, beanName, specificInterceptors, targetSource);
//把生成的代理对象进行缓存
this.proxyTypes.put(cacheKey, proxy.getClass());
//返回该代理对象,在上一级方法中,有做后置通知方法的处理
return proxy;
} else {
return null;
}
}
protected boolean isInfrastructureClass(Class> beanClass) {
return super.isInfrastructureClass(beanClass) || this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass);
}
protected boolean isInfrastructureClass(Class> beanClass) {
//如果bean继承自Advice、Pointcut、Advisor、AopInfrastructureBean
boolean retVal = Advice.class.isAssignableFrom(beanClass) || Pointcut.class.isAssignableFrom(beanClass) || Advisor.class.isAssignableFrom(beanClass) || AopInfrastructureBean.class.isAssignableFrom(beanClass);
if (retVal && this.logger.isTraceEnabled()) {
this.logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
}
return retVal;
}
public boolean isAspect(Class> clazz) {
//如果bean带有@Aspect注解,并且不能被Ajc(AspectJ编译器)编译
return this.hasAspectAnnotation(clazz) && !this.compiledByAjc(clazz);
}
(1)判断当前bean是否在advisedBeans中(保存了所有需要增强bean,使用Boolean区分是否可以被代理。false可以理解为切面类,不需要代理的;如果是true,表示被切的类,表明已经生成过代理了(即切面逻辑已经应用到该bean));
(2)判断当前bean是否是基础类型的Advice、Pointcut、Advisor、AopInfrastructureBean、判断是否是切面(是否实现了注解@Aspect)、判断是否需要跳过; 注:因为是切面类(标注@Aspect),则会advisedBeans.put(cacheKey, Boolean.FALSE),加入到增强Bean的map集合中,并返回null,然后到上一级程序继续执行下一步。
(3)如果用户使用了自定义的TargetSource对象,则直接使用该对象生成目标对象,而不会使用Spring的默认逻辑生成目标对象,并且这里会判断各个切面逻辑是否可以应用到当前bean上,如果可以,则直接应用,也就是说TargetSource为使用者在Aop中提供了一个自定义生成目标bean逻辑的方式,并且会应用相应的切面逻辑。即在这一步就已经把切面逻辑应用在了该bean上,并生成了代理对象。在这之后直接返回该bean,createBean方法结束。
4.1.2. 初始化bean之后
->执行doCreateBean->initializeBean->InstantiationAwareBeanPostProcessor.postProcessBeforeInitialization 未作特别处理,可忽略 ->执行doCreateBean->initializeBean->InstantiationAwareBeanPostProcessor.postProcessAfterInitialization->wrapIfNecessary 判断该bean是否需要增强,如果需要增强,则创建一个该bean的代理对象。因为是切面类,所以不需要增强,返回bean
补充:在实例化bean前后使用的后置处理器并不一定是一个,而是会把所有的后置处理器(每个后置处理器方法都有before和after,处理时机不同)都遍历一遍(处理器按照一定顺序)来处理当前的bean。
4.2.1. 实例化bean之前
执行resolveBeforeInstantiation->InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation(执行方法同上面切面类里的方法)
(1)判断当前bean是否在advisedBeans中(保存了所有需要增强bean);
(2)判断当前bean是否是基础类型的Advice、Pointcut、Advisor、AopInfrastructureBean、判断是否是切面(是否实现了注解@Aspect)、判断是否需要跳过;
(3)如果用户使用了自定义的TargetSource对象,则直接使用该对象生成目标对象,而不会使用Spring的默认逻辑生成目标对象,并且这里会判断各个切面逻辑是否可以应用到当前bean上,如果可以,则直接应用,也就是说TargetSource为使用者在Aop中提供了一个自定义生成目标bean逻辑的方式,并且会应用相应的切面逻辑。
注:因为是需要被切的类,所以以上三个条件都不满足,既不在advisedBeans中,也不是基础类等,更不是自定义的TargetSource对象,所以这个过程未作特别处理,返回null。
4.2.2. 初始化bean之后
->执行doCreateBean->initializeBean->InstantiationAwareBeanPostProcessor.postProcessBeforeInitialization 未作特别处理,可忽略 ->执行doCreateBean->initializeBean->InstantiationAwareBeanPostProcessor.postProcessAfterInitialization->wrapIfNecessary
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
//如果是targetSourcedBeans存放已经增强过的bean,则不需要再次处理
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
} else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
//advisedBeans的key为cacheKey,value为boolean类型,表示是否进行过代理
//已经处理过的(切面)bean,不需要再次进行处理,节省时间
return bean;
} else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
//如果不是内部基础设置类Class && 不需要跳过(即配置了该bean需要代理,则不需要跳过)
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
}
(1)未被增强处理过,且未被代理过,且不是基础方法,且不需要跳过的,才能执行下一步; (2)执行getAdvicesAndAdvisorsForBean,获取当前对象所有适用的Advisor(即切面类实例),主要处理两件事。具体逻辑如下,
protected Object[] getAdvicesAndAdvisorsForBean(Class> beanClass, String beanName, @Nullable TargetSource targetSource) {
List advisors = this.findEligibleAdvisors(beanClass, beanName);
return advisors.isEmpty() ? DO_NOT_PROXY : advisors.toArray();
}
protected List findEligibleAdvisors(Class> beanClass, String beanName) {
//找到Spring中Advisor的实现类(findCandidateAdvisors)
//将所有拥有@Aspect注解的类转换为advisors(aspectJAdvisorsBuilder.buildAspectJAdvisors)
List candidateAdvisors = this.findCandidateAdvisors();
//找到当前对象适合的所有Advisor
List eligibleAdvisors = this.findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
//添加一个默认的advisor,执行时用到
this.extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = this.sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
第一步,执行findCandidateAdvisors(),其中执行父级findCandidateAdvisors,找到Spring中Advisor的实现类(已经存在的Advisor);然后执行aspectJAdvisorsBuilder.buildAspectJAdvisors,将所有拥有@Aspect注解的类转换为advisors(转换的过程,其实就是创建Advisor的过程,本质是创建InstantiationModelAwarePointcutAdvisorImpl对象);最终把所有的切面类实例advisors放到list中。具体逻辑如下,
protected List findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules
List advisors = super.findCandidateAdvisors();
if (this.aspectJAdvisorsBuilder != null) {
// Build Advisors for all AspectJ aspects in the bean factory
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
super.findCandidateAdvisors()方法最终调用advisorRetrievalHelper.findAdvisorBeans(),逻辑如下,
public List findAdvisorBeans() {
String[] advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
// 获取当前BeanFactory中所有实现了Advisor接口的bean的名称
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
if (advisorNames.length == 0) {
return new ArrayList();
} else {
List advisors = new ArrayList();
String[] var3 = advisorNames;
int var4 = advisorNames.length;
// 对获取到的实现Advisor接口的bean的名称进行遍历
for(int var5 = 0; var5 < var4; ++var5) {
String name = var3[var5];
// isEligibleBean()是提供的一个hook方法,用于子类对Advisor进行过滤,这里默认返回值都是true
if (this.isEligibleBean(name)) {
// 如果当前bean还在创建过程中,则略过,其创建完成之后会为其判断是否需要织入切面逻辑
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isTraceEnabled()) {
logger.trace("Skipping currently created advisor '" + name + "'");
}
} else {
try {
// 将当前bean添加到advisors结果中
advisors.add(this.beanFactory.getBean(name, Advisor.class));
} catch (BeanCreationException var11) {
// 对获取过程中产生的异常进行封装
Throwable rootCause = var11.getMostSpecificCause();
if (rootCause instanceof BeanCurrentlyInCreationException) {
BeanCreationException bce = (BeanCreationException)rootCause;
String bceBeanName = bce.getBeanName();
if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
if (logger.isTraceEnabled()) {
logger.trace("Skipping advisor '" + name + "' with dependency on currently created bean: " + var11.getMessage());
}
continue;
}
}
throw var11;
}
}
}
}
return advisors;
}
}
aspectJAdvisorsBuilder.buildAspectJAdvisors()会触发ReflectiveAspectJAdvisorFactory中的getAdvisors方法,逻辑如下,
public List getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
//从 aspectMetadata 中获取 Aspect()标注的类 class对象
Class> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
//获取Aspect()标注的类名
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
this.validate(aspectClass);
// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
// so that it will only instantiate once.
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List advisors = new ArrayList();
//遍历该类所有方法,根据方法判断是否能获取到对应 pointCut,如果有,则生成 advisor 对象
Iterator var6 = this.getAdvisorMethods(aspectClass).iterator();
while(var6.hasNext()) {
Method method = (Method)var6.next();
//这里继续看下面的解析
Advisor advisor = this.getAdvisor(method, lazySingletonAspectInstanceFactory, 0, 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 ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}
Field[] var12 = aspectClass.getDeclaredFields();
int var13 = var12.length;
//获取 @DeclareParents 注解修饰的属性(并不常用)
for(int var14 = 0; var14 < var13; ++var14) {
Field field = var12[var14];
Advisor advisor = this.getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
getAdvisor的具体逻辑如下,
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrderInAspect, String aspectName) {
this.validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
AspectJExpressionPointcut expressionPointcut = this.getPointcut(candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
//构建InstantiationModelAwarePointcutAdvisorImpl对象
return expressionPointcut == null ? null : new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
InstantiationModelAwarePointcutAdvisorImpl会触发getAdvice,具体逻辑如下,
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
...
Object springAdvice;
//根据注解类型,匹配对应的通知类型
switch(aspectJAnnotation.getAnnotationType()) {
//切面
case AtPointcut:
if (this.logger.isDebugEnabled()) {
this.logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
//环绕通知
case AtAround:
springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
//前置通知
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
//最终通知
case AtAfter:
springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
//后置(正常)通知
case AtAfterReturning:
springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning)aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
((AbstractAspectJAdvice)springAdvice).setReturningName(afterReturningAnnotation.returning());
}
break;
//异常通知
case AtAfterThrowing:
springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterThrowing afterThrowingAnnotation = (AfterThrowing)aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
((AbstractAspectJAdvice)springAdvice).setThrowingName(afterThrowingAnnotation.throwing());
}
break;
default:
throw new UnsupportedOperationException("Unsupported advice type on method: " + candidateAdviceMethod);
}
...
return (Advice)springAdvice;
}
}
其本质是根据@Aspect
类中方法的注解类型,生成对应的advice
,并通过通知的构造方法,将通知增强方法,切面表达式传入到通知当中。
第二步,执行findAdvisorsThatCanApply,找到当前对象适合的所有Advisor。整个过程比较简单:遍历所有的advisor,然后查看当前advisor的pointCut是否适用于当前对象,如果是,进入候选队列(其实就是放到一个list中),否则跳过。
(3)执行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);
//检查proxyTargeClass设置以及preserveTargetClass属性
//决定对于给定的bean是否应该使用targetClass而不是他的接口代理
if (!proxyFactory.isProxyTargetClass()) {
if (this.shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
} else {
//用来添加代理接口
this.evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = this.buildAdvisors(beanName, specificInterceptors);
//加入增强器
proxyFactory.addAdvisors(advisors);
//设置要代理的类
proxyFactory.setTargetSource(targetSource);
//定制代理
this.customizeProxyFactory(proxyFactory);
//用来控制代理工厂被设置后是否还允许修改通知,缺省值为false
proxyFactory.setFrozen(this.freezeProxy);
if (this.advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(this.getProxyClassLoader());
}
从上面代码我们看到对于代理类的创建及处理spring是委托给了ProxyFactory处理的,而在此函数中主要是对ProxyFactory的初始化操作,进而对创建代理做准备,这些初始化操作包括以下内容: 第一步,获取当前类中的属性 第二步,添加代理接口
下面是添加代理接口evaluateProxyInterfaces的函数:
protected void evaluateProxyInterfaces(Class> beanClass, ProxyFactory proxyFactory) {
Class>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, this.getProxyClassLoader());
boolean hasReasonableProxyInterface = false;
Class[] var5 = targetInterfaces;
int var6 = targetInterfaces.length;
int var7;
Class ifc;
for(var7 = 0; var7 < var6; ++var7) {
ifc = var5[var7];
if (!this.isConfigurationCallbackInterface(ifc) && !this.isInternalLanguageInterface(ifc) && ifc.getMethods().length > 0) {
hasReasonableProxyInterface = true;
break;
}
}
if (hasReasonableProxyInterface) {
var5 = targetInterfaces;
var6 = targetInterfaces.length;
for(var7 = 0; var7 < var6; ++var7) {
ifc = var5[var7];
proxyFactory.addInterface(ifc);
}
} else {
proxyFactory.setProxyTargetClass(true);
}
}
第三步,封装Advisor并加入到ProxyFactory中 第四步,设置要代理的类 第五步,在spring中还为子类提供了定制的函数customizeProxyFactory,子类可以在此函数中进行对ProxyFactory的进一步封装 第六步,进行获取代理操作
上面proxyFactory.getProxy中的createAopProxy()最终调用的是DefaultAopProxyFactory.createAopProxy()的实现逻辑如下,
public Object getProxy(@Nullable ClassLoader classLoader) {
return this.createAopProxy().getProxy(classLoader);
}
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
return new JdkDynamicAopProxy(config);
} else {
Class> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: Either an interface or a target is required for proxy creation.");
} else {
return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
}
}
}
注意:如果bean是需要被切的类(如开始举的UserServiceImpl例子),那么在bean缓存池中存放的就是带有切面逻辑的代理对象,该代理对象属性中包含advisors(结构是ArrayList,里面存放的是切点和通知,就是我们常用的@Aspect 注解标记的类),具体参考下面几张结果图,
如下可以看出,在beanPostProcessors后置处理器集合中,有AnnotationAwareAspectJAutoProxyCreator对象这里有userServiceImpl这个因被切而生成的代理对象(已经应用了切面逻辑)属性,并且使用的是CGLib代理。
如下图,可以看出在bean缓存池中,存放了userServiceImpl的代理对象(注意没有再单独的userServiceImpl对象了,因为userServiceImpl被切了,所以bean缓存吃中保存的只有userServiceImpl的代理对象),该代理对象下有切点和通知,在后续使用该bean的时候,会用到这里的其切点和通知,会转换成拦截器,并形成拦截器链,保证通知方法按顺序执行。
如上面的userServiceImpl,实际存到bean缓存池中存放的就是带有切面逻辑的代理对象,如上的userServiceImpl就是一个cglib代理对象,在执行到该方法的时候,获取到的该bean就是这个cglib代理对象,所以执行他的方法的时候,首先会进入cglib代理对象的拦截器,即CglibAopProxy.intercept()拦截器,其中会获取即将执行的目标方法的拦截器链。具体逻辑如下,
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
Object var16;
try {
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
Class> targetClass = target != null ? target.getClass() : null;
//根据ProxyFactory对象获取将要执行的目标方法拦截器链
List
(1)执行advised.getInterceptorsAndDynamicInterceptionAdvice,
1)List
2)遍历所有的增强器,将每个增强器转为MethodInterceptor,具体为,每个增强其都执行registry.getInterceptors(advisor),其流程为:
如果是MethodInterceptor 直接加入到List
如果不是,使用AdvisorAdapter将增强器转为MethodInterceptor;
转换完成返回MethodInterceptor[]数组。
3)如果没有拦截器链,直接执行目标方法; 拦截器链(每一个通知方法又被包装为方法拦截器,利用MethodInterceptor机制)
4)如果有拦截器链,把需要执行的目标对象,目标方法,拦截器链等信息传入创建一个 CglibMethodInvocation 对象,并调用 Object retVal = mi.proceed();
5)拦截器链的触发过程; 第一步,如果没有拦截器执行执行目标方法,或者拦截器的索引和拦截器数组-1大小一样(指定到了最后一个拦截器)执行目标方法; 第二步,链式获取每一个拦截器,拦截器执行invoke方法,每一个拦截器等待下一个拦截器执行完成返回以后再来执行; 拦截器链的机制,保证通知方法与目标方法的执行顺序;
(1)@EnableAspectJAutoProxy 开启AOP功能,即往bean定义注册表中注册AnnotationAwareAspectJAutoProxyCreator;
(2)AnnotationAwareAspectJAutoProxyCreator是一个后置处理器,这里提供了获取适用当前bean的切面逻辑,并把切面逻辑应用到该bean,最后创建一个代理对象的所有方法,所以他是spring提供aop功能的核心;
(3)IOC容器的创建流程(以下为与AOP初始化相关的逻辑):
1)refresh.registerBeanPostProcessors()注册后置处理器;创建AnnotationAwareAspectJAutoProxyCreator对象
2)finishBeanFactoryInitialization()初始化剩下的单实例bean
1.如果是切面类,则advisedBeans.put(cacheKey, Boolean.FALSE),加入到增强Bean的map集合中;
2.如果是自定义的TargetSource对象,则直接使用该对象生成目标对象,而不会使用Spring的默认逻辑生成目标对象,并且这里会判断各个切面逻辑是否可以应用到当前bean上,如果可以,则直接应用,也就是说TargetSource为使用者在Aop中提供了一个自定义生成目标bean逻辑的方式,并且会应用相应的切面逻辑。
3.如果是需要被切的类,则获取当前对象所有适用的Advisor(即切面类实例),并把Advisor应用到该bean,并最终创建一个代理对象,这个过程被成为增强;
(4)执行目标方法:
1)代理对象执行目标方法
2)CglibAopProxy.intercept();
1.得到目标方法的拦截器链(增强器包装成拦截器MethodInterceptor)
2.利用拦截器的链式机制,依次进入每一个拦截器进行执行;
3.效果: 正常执行:前置通知-》目标方法-》返回通知-》后置通知 出现异常:前置通知-》目标方法-》异常通知-》后置通知
(5)AOP中几个重要的概念
1)切面(aspect):类是对物体特征的抽象,切面就是对横切关注点的抽象,在Spring中意为所有通知方法所在的类,如上例中使用@Aspect注解的(LogAspects)切面类。
2)连接点(Join point):被拦截到的点,因为 Spring 只支持方法类型的连接点,所以在 Spring 中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器,如上面被拦截到的userServiceImpl.add方法就是连接点。
3)切入点(pointcut):与通知一起出现,使用专门的切点表达式决定在何处执行通知方法,如上例使用的@Pointcut注解设计到具体类或方法,就是切入点。
4)通知(advice):所谓通知指的就是指拦截到连接点之后要执行的代码,共有5种类型,before(切点之前执行),around(环绕执行,即切点前后执行),After returning(切点正常执行完返回后执行),After throwing(切点抛出异常后执行),after(切点之后执行,不管是异常或正常结束),AOP拦截器链则为以上五种通知组成。我们可以在通知方法中获得我们需要的参数(返回值,异常信息,代理对象等)。
5)目标对象(target object):代理的目标对象,如上例中的UserServiceImpl就是目标对象。
6)织入(weaving):将切面应用到目标对象并导致代理对象创建的过程,Spring AOP是动态织入(运行时织入),AspectJ则是静态织入(编译时织入),如上例执行的wrapIfNecessary方法执行的过程就是织入。
7)引入(introduction):在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或属性,例如,可以使用引入来使一个bean实现isModified接口,以便简化缓存机制。
8)AOP代理(AOP proxy):AOP代理对象,由JDK动态代理或CGLIB代理生成。
(6)扩展:spring boot中的事务处理,本质跟上面的AOP逻辑类似,
1)Sringboot启动类上添加@EnableTransactionManagement,
@EnableTransactionManagement引入的是TransactionManagementConfigurationSelector。该类引入两个组件,分别是AutoProxyRegistrar和ProxyTransactionManagementConfiguration。
AutoProxyRegistrar会去创建InfrastructureAdvisorAutoProxyCreator的beandefinition,这个是bean的后置处理器,做的事情和上面的AOP的AnnotationAwareAspectJAutoProxyCreator类似。
ProxyTransactionManagementConfiguration它是一个配置类,里面包括有一些bean方法,在最后创建bean时,这些beanMethod返回的bean都会创建对象添加到iOC容器。其中包括有: BeanFactoryTransactionAttributeSourceAdvisor、AnnotationTransactionAttributeSource、TransactionInterceptor。作用其实就是个切面类,定义了一些切面逻辑。
2)在需要使用事务的方法上加@Transactional,实现事务操作。