文章目录
- 1 AOP
- 2 我们看到在我们配置类上加入了@EnableAspectJAutoProxy这个东东?我们着重来分析一下这个东东给我容器中添加了什么组件?
- 3 所以我们现在可以分析一下AnnotationAwareAspectJAutoProxyCreator 他是什么一个鬼?
- 4 真正的创建代理对象从BeanPostProcessor处理器的后置方法开始
-
- 4.1 org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization源码分析
- 4.2 org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary源码分析
- 4.3 org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean 源码分析
- 4.4 org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findEligibleAdvisors
- 4.5 org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findCandidateAdvisors 从IOC容器中查找所有的增强器
- 4.6 org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply
- 5 代理对象调用目标方法
- 6 AOP步骤总结
1 AOP
1.1 AOP
AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如安全性、异常处理和透明的持续性也都是如此,这种散布在各处的无关的代码被称为横切(cross cutting),在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
AOP技术恰恰相反,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。
使用"横切"技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。
1.2 基本概念
AOP核心概念
1、横切关注点(对哪些方法进行切入)
对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点
2、切面(aspect,把原来糅杂在业务逻辑代码中的非业务代码抽取出来,把功能相同的放在一个类中形成一个切面)
类是对物体特征的抽象,切面就是对横切关注点的抽象
3、连接点(joinpoint)(需要切入的点)
被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器
4、切入点(pointcut)
对连接点进行拦截的定义
5、通知(advice)
所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类
6、目标对象
代理的目标对象
7、织入(weave)
将切面应用到目标对象并导致代理对象创建的过程
8、引入(introduction)
在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段
1.3 简单案例:
public interface Calculate {
/**
* 加法
* @param numA
* @param numB
* @return
*/
int add(int numA,int numB);
/**
* 减法
* @param numA
* @param numB
* @return
*/
int reduce(int numA,int numB);
/**
* 除法
* @param numA
* @param numB
* @return
*/
int div(int numA,int numB);
/**
* 乘法
* @param numA
* @param numB
* @return
*/
int multi(int numA,int numB);
}
=====================实现类
public class TulingCalculate implements Calculate {
public int add(int numA, int numB) {
return numA+numB;
}
public int reduce(int numA, int numB) {
return numA-numB;
}
public int div(int numA, int numB) {
return numA/numB;
}
public int multi(int numA, int numB) {
return numA*numB;
}
}
=====================切面类=====================
@Aspect
public class TulingLogAspect {
@Pointcut("execution(* com.tuling.TulingCalculate.*(..))")
public void pointCut(){
};
@Before(value = "pointCut()")
public void methodBefore(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();
System.out.println("执行目标方法【"+methodName+"】之前执行<前置通知>,入参"+ Arrays.asList(joinPoint.getArgs()));
}
@After(value = "pointCut()")
public void methodAfter(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("执行目标方法【"+methodName+"】之前执行<后置通知>,入参"+Arrays.asList(joinPoint.getArgs()));
}
@AfterReturning(value = "pointCut()")
public void methodReturning(JoinPoint joinPoint ) {
String methodName = joinPoint.getSignature().getName();
System.out.println("执行目标方法【"+methodName+"】之前执行<返回通知>,入参"+Arrays.asList(joinPoint.getArgs()));
}
@AfterThrowing(value = "pointCut()")
public void methodAfterThrowing(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("执行目标方法【"+methodName+"】之前执行<异常通知>,入参"+Arrays.asList(joinPoint.getArgs()));
}
}
===========================配置类=============
@Configuration
@EnableAspectJAutoProxy
public class MainConfig {
@Bean
public Calculate calculate() {
return new TulingCalculate();
}
@Bean
public TulingLogAspect tulingLogAspect() {
return new TulingLogAspect();
}
}
2 我们看到在我们配置类上加入了@EnableAspectJAutoProxy这个东东?我们着重来分析一下这个东东给我容器中添加了什么组件?
2.1 我们发现@EnableAspectJAutoProxy上标注了一个@Import注解,通过前面的学习我们知道@Import可以给我们容器中添加组件
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
2.2 所以我们来分析AspectJAutoProxyRegistrar类是用来干什么的?
经过跟踪源代码我们发现,AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrar接口,我们以前学习过
凡是实现了ImportBeanDefinitionRegistrar可以给我们容器中添加bean定义信息
作用:往容器中注册了一个名称叫org.springframework.aop.config.internalAutoProxyCreator
类型为AnnotationAwareAspectJAutoProxyCreator 注解的apsectj自动代理创建器
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//往容器中注册对应的 aspectj注解自动代理创建器
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
//注册一个AnnotationAwareAspectJAutoProxyCreator(注解适配的切面自动创建器)
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
//判断容器中有没有org.springframework.aop.config.internalAutoProxyCreator 名称的bean定义
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
//容器中没有 那么就注册一个名称叫org.springframework.aop.config.internalAutoProxyCreator 类型是AnnotationAwareAspectJAutoProxyCreator的bean定义
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
3 所以我们现在可以分析一下AnnotationAwareAspectJAutoProxyCreator 他是什么一个鬼?
根据上述类图
1)我们发现了AnnotationAwareAspectJAutoProxyCreator 有实现了***Aware接口的特性(BeanFactoryAware)
2)还发现了AnnotationAwareAspectJAutoProxyCreator 实现了BeanPostProcessor接口(后置处理器的特性)
3)还发现了AnnotationAwareAspectJAutoProxyCreator 实现了InstantiationAwareBeanPostProcessor接口(后置处理器的一种,在实例化之前进行调用)
我们根据上AnnotationAwareAspectJAutoProxyCreator 的类的继承图来分析AnnotationAwareAspectJAutoProxyCreator 的功能
3.1 所以我们首先来分析AnnotationAwareAspectJAutoProxyCreator 实现了BeanFactoryAware接口 做了什么工作?
①:org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator 实现了BeanFactoryAware
我们查看源码的时候发现AbstractAutoProxyCreator 的setBeanFactory()方法啥都没有做,但是又被子类覆盖了
@Override
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
②:AbstractAdvisorAutoProxyCreator覆盖了AbstractAutoProxyCreator.setBeanFactory()方法
做了二件事情
1 调用父类的super.setBeanFactory(beanFactory);
2 调用本来的initBeanFactory((ConfigurableListableBeanFactory) beanFactory);初始化bean工厂方法
但是本类的AbstractAdvisorAutoProxyCreator.initBeanFactory()又被子类覆盖了
public void setBeanFactory(BeanFactory beanFactory) {
//调用父类AbstractAutoProxyCreator.setBeanFactory()方法
super.setBeanFactory(beanFactory);
if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
throw new IllegalArgumentException(
"AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
}
//初始化bean工程
initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
}
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);
}
③:AnnotationAwareAspectJAutoProxyCreator#initBeanFactory覆盖了AbstractAdvisorAutoProxyCreator.initBeanFactory()方法
//创建一个aop的增强器通过@Apsectj注解的方式.
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
//调用父类的
super.initBeanFactory(beanFactory);
//若 apsectj的增强器工厂对象为空,我们就创建一个ReflectiveAspectJAdvisorFactory
if (this.aspectJAdvisorFactory == null) {
this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
}
//不为空 我们就把aspectJAdvisorFactory 包装为BeanFactoryAspectJAdvisorsBuilderAdapter
this.aspectJAdvisorsBuilder =
new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
}
总结:AnnotationAwareAspectJAutoProxyCreator 实现了BeanFactoryAware 也是做了二个事情
1 把Beanfactory 保存到AnnotationAwareAspectJAutoProxyCreator 组件上.
2 为AnnotationAwareAspectJAutoProxyCreator 的aspectJAdvisorsBuilder aspect增强器构建器赋值
3.2 还发现了AnnotationAwareAspectJAutoProxyCreator 实现了BeanPostProcessor接口(后置处理器的特性)
我们追根溯源 AbstractAutoProxyCreator类实现了BeanPostProcessor接口 所以我们分析BeanPostProcessor的二个方法
①:postProcessBeforeInitialization初始化之前的方法 貌似什么都没有干
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
②:postProcessAfterInitialization 这个方法很重要 很重要 后面单独说(创建代理对象的逻辑)
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;
}
3.3 还发现了AnnotationAwareAspectJAutoProxyCreator 实现了InstantiationAwareBeanPostProcessor接口(后置处理器的一种,在实例化之前进行调用)
InstantiationAwareBe