赞
踩
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<Advisor> 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<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
List<Advisor> 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; }
在这里很明显是对bean进行各种判断,看是否需要创建代理对象。创建代理的流程如下所示:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。