AOP (Aspect Orient Programming),直译过来就是 面向切面编程。AOP 是一种编程思想,是面向对象编程(OOP)的一种补充。面向对象编程将程序抽象成各个层次的对象,而面向切面编程是将程序抽象成各个切面,是Spring的核心思想之一。
AOP 要达到的效果是,保证开发者不修改源代码的前提下,去为系统中的业务组件添加某种通用功能。AOP 的本质是由 AOP 框架修改业务组件的多个方法的源代码,按照 AOP 框架修改源代码的时机,可以将其分为两类:
我们知道,spring中的aop是通过动态代理实现的,那么他具体是如何实现的呢?spring通过一个切面类,在他的类上加入@Aspect注解,定义一个Pointcut方法,最后定义一系列的增强方法。这样就完成一个对象的切面操作。
那么思考一下,按照上述的基础,要实现我们的aop,大致有以下思路:
1.找到所有的切面类
2.解析出所有的advice并保存
3.创建一个动态代理类
4.调用被代理类的方法时,找到他的所有增强器,并增强当前的方法
spring通过@EnableAspectJAutoProxy开启aop切面,在注解类上面发现@Import(AspectJAutoProxyRegistrar.class),AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrar,所以他会通过registerBeanDefinitions方法为我们容器导入beanDefinition。
AspectJAwareAdvisorAutoProxyCreator的类图,如下所示:
IOC容器中注入了一个internalAutoProxyCreator=AnnotationAwareAspectJAutoProxyCreator的bean,到此可以得出结论,@EnableAspectJAutoProxy给容器中注册一个AnnotationAwareAspectJAutoProxyCreator。
在创建bean的时候会调用AbstractAutoProxyCreator的postProcessBeforeInstantiation(Class> beanClass, String beanName) ,源码如下:
public Object postProcessBeforeInstantiation(Class> beanClass, String beanName) {
//构建缓存key
Object cacheKey = getCacheKey(beanClass, beanName);
// 没有beanName 或者 没有包含在targetSourcedBeans中(一般都不会包含,因为targetSource需要手动设置,一般情况不会设置)
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
//被解析过 直接返回
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
/*
*判断是不是基础的bean (是不是切面类、通知、切点等)
*判断是不是应该跳过 默认false (切面解析也在其中),shouldSkip是做切面解析的
*/
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
/*
*/
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
//获取Advices和Advisor从Bean中
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
//创建代理对象
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
找到方法中的shouldSkip(beanClass, beanName),是否应该跳过,进入方法内部
@Override
protected boolean shouldSkip(Class> beanClass, String beanName) {
// TODO: Consider optimization by caching the list of the aspect names
//到候选的Advisors(通知 前置通知、后置通知等..)
List candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
if (advisor instanceof AspectJPointcutAdvisor &&
((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
return true;
}
}
return super.shouldSkip(beanClass, beanName);
}
方法中可以看到,只有一个findCandidateAdvisors()方法的调用,直接进入findCandidateAdvisors()
@Override
protected List findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
List advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
这里的代码分为两个部分,一个是父类的实现,一部分是子类的实现,这里主要关注子类的实现可以看到核心方法buildAspectJAdvisors()。切面类解析主要的工作就是在这类中。
继续查看AbstractAutoProxyCreator的源码,我们发现AbstractAutoProxyCreator还有postProcessAfterInstantiation,postProcessProperties类似的方法,但都是空的,有一个postProcessAfterInitialization不是空方法,于是我们进入方法内部发现就是我们要找的createProxy
的方法。
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
//获取缓存key
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// 之前循环依赖创建的动态代理 如果是现在的bean 就不再创建,,并且移除
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 该方法将会返回动态代理实例
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
进入到wrapIfNecessary方法,如下所示,很容易看到// Create proxy if we have advice.的注解。
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
//已经被处理过(解析切面时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;
}
// Create proxy if we have advice.
// 根据当前bean找到匹配的advisor
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// 当前bean匹配到了advisor
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;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}