苦行僧DH

博客园 首页 新随笔 联系 订阅 管理

1、概述

它最大的作用是什么?

在不更改源代码的情况下,对其原有功能进行增强。使得代码的重用率、开发效率、维护产生极大的方便。

运用场景

最常见的有:事务、日志、请求拦截等

2、使用

如何在Spring中使用AOP?

1、开启配置

@EnableAspectJAutoProxy

2、写代理类和被代理的类

@Component
@Aspect
public class AopConfig {

	@PostConstruct
	public void init(){
		System.out.println();
	}

	@Pointcut("execution(* com.dh.aop.package1.Demo1.*(..))")
	public void pointCut(){}

	@Before("pointCut()")
	public void before(){
		System.out.println("before running... ");
	}
}

@Component
public class Demo1 {
	
	public void testAop(){
		System.out.println("com.dh.aop.package1.Demo1.test1 running...");
	}

}

当我们从容器中拿出Demo1调用testAop的时候,打印如下:

before running... 
com.dh.aop.package1.Demo1.test1 running...

这就是现象,

3、原理

本文不讲应用,讲的是AOP在Spring实现的位置,具体实现的逻辑代码下一篇说。

首先我们看从Spring容器中拿到的Demo1的对象:

这里很明显,我们的Demo1并不是我们自己写的Demo1了,而是被代理后的Demo1,此代理为Cglib代理,且在我们的类中加入了几个变量,这个变量不是重点,是cglib做一些回调的扩展。

那么到这里我们就能知道,Spring使用Cglib对我们的原始类进行代理,那么Spring是在哪里对我们的类进行代理的呢?

首先我们要知道,Spring的执行流程如下:

这个图是Spring的执行流程,我们这里要找的方法在refresh的registerBeanPostProcessors和finishBeanFactoryInitialization方法。

registerBeanPostProcessors()

注册BeanPostProcessor后置处理器,这里的BeanPostProcessor是Spring的后置处理器,可用与我们的Bean实例化以后,对我们的Bean进行改变的类,例如下:

public class TestMyProxyBeanPostProcess implements BeanPostProcessor {

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		if (bean instanceof Demo1){
			/** 代理Demo1这个类 */
			bean = 代理的类
		}
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if (bean instanceof Pojo1){
		}
		return bean;
	}
}

这里可以直接将bean的值更改,并且return回去当做新的bean。

在我们Spring当中,AOP功能就是使用BeanPostProcessor来实现的。此BeanPostProcessor的名字为:AnnotationAwareAspectJAutoProxyCreator。

加入此后置处理器的配置其实就是因为我们的@EnableAspectJAutoProxy,此注解中拥有一个@Import(AspectJAutoProxyRegistrar.class)注解,此AspectJAutoProxyRegistrar中执行回调时有一行代码AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);就是加入此后置处理器的。

finishBeanFactoryInitialization()

我们Spring当中所有的单例Bean都是在此方法中进行初始化的(我们这里不讲Bean初始化,只讲AOP的实现位置),我们定位代码到:

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

可以看到我们的Demo1已经实例化出来了:

且此时是原始的对象,并没有实例化,那么我们再往下面走:

注意看,此initializeBean方法执行完的返回值Object就是Demo1的代理类,且为Cglib代理,那么就说明实现AOP代理的方法就这个org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)方法,进入这个方法看看:

注意此时bean还是原始对象,而不是代理对象,我们F6走下一步后:

我们的bean变成了代理对象,那么说明重要的代码就在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization方法当中去:

这里要遍历getBeanPostProcessor拿到的BeanPostProcessor的postProcessAfterInitialization方法,并将返回值赋值给当前的bean,相当于是更改了Bean。我们来看看getBeanPostProcessor这个方法的返回值有哪些BeanPostProcessor:

我们看这里的这个第3个元素的PostProcessor,此就是我们前面@EnableAspectJAutoProxy注解加入的BeanPostProcessor,我们进入这个循环,看看当这个Processor执行完后是否bean就变成了代理对象。

当前是循环到我们的AnnotationAwareAspectJAutoProxyCreator了,且当前bean仍然是原始类,现在我们F6走一步:

看我们的Bean已经变成了代理类,那么我们这里就明白了实现代理AOP的位置了,下面我们简单的看看AnnotationAwareAspectJAutoProxyCreatorpostProcessAfterInitialization方法,看看它咋做的。

更重点的就是org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization此方法的wrapIfNecessary方法:

这个方法的代码里面怎么实现的AOP,我们下次再聊

posted on 2021-09-07 09:19  苦行僧DH  阅读(509)  评论(0编辑  收藏  举报