Spring AOP原理
@EnableAspectJAutoProxy
首先来看 @EnableAspectJAutoProxy 这个注解:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
// 使用cglib代理
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
可以看到他导入了一个 AspectJAutoProxyRegistrar 组件,AspectJAutoProxyRegistrar 是 ImportBeanDefinitionRegistrar的实现类,前面我们说过可以通过实现 ImportBeanDefinitionRegistrar 接口的方式向容器中注册 BeanDefinition。
于是,在接下来的环节中:
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
// AopConfigUtils
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
可以看到这里其实是注入了一个 AnnotationAwareAspectJAutoProxyCreator 。
因此我们可以得出结论:@EnableAspectJAutoProxy 注解其实就是通过 @Import 向容器中注册了一个AnnotationAwareAspectJAutoProxyCreator。
AnnotationAwareAspectJAutoProxyCreator
我们先来一起看一下类图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5gfN73Rn-1625460544047)(D:\学习\001-张帅鹏面试\05-框架\AnnotationAwareAspectJAutoProxyCreator类图.png)]
可以看到,AnnotationAwareAspectJAutoProxyCreator 是 BeanFactoryAware 和 SmartInstantiationAwareBeanPostProcessor 的子类。
那么,从这里我们就可以得知它的执行时机:
-
BeanFactoryAware:在bean的实例化过程中的 initializeBean() 方法中的第一步,invokeAwareMethod(),处理Aware接口的回调
-
SmartInstantiationAwareBeanPostProcessor:
- AbstractAutowireCapableBeanFactory 中 createBean() 方法的这一行,即在执行doCreateBean() 之前,InstantiationAwareBeanPostProcessor有机会返回Bean实例,如果是第一次执行则返回为空。
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. // 第一个执行时机 Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
-
在执行Bean自定义初始化方法的前后执行 before 和 after 方法
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { ... invokeAwareMethods(beanName, bean); ... // 第二个执行时机 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); ... invokeInitMethods(beanName, wrappedBean, mbd); .... // 第三个执行时机 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); }
现在我们知道了 AnnotationAwareAspectJAutoProxyCreator 的执行时机,那么接下来就一起看一下 AOP 代理是如何创建的。
resolveBeforeInstantiation(beanName, mbdToUse)
AbstractApplicationContext.refresh() 中的 finishBeanFactoryInitialization(beanFactory) 方法用来加载剩下未实例化的单例bean,其中在执行 doCreateBean() 创建bean实例之前有最后一次机会可以返回实例bean,从而终止后面创建bean实例的过程,代码如下:
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
接下来会获取容器中所有的 InstantiationAwareBeanPostProcessor 来执行他们的 postProcessBeforeInstantiation 方法(),如果 postProcessBeforeInstantiation() 方法可以返回实例Bean,就会继续执行 postProcessAfterInstantiation() 方法。由于 AnnotationAwareAspectJAutoProxyCreator 也是 InstantiationAwareBeanPostProcessor 的子类,因此在这里也会被执行,代码如下:
@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
// 依次执行所有InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation()方法
Object result = bp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
return null;
}
接下来我们来一起看一下在 AnnotationAwareAspectJAutoProxyCreator 的 postProcessBeforeInstantiation() 中做了什么,以下是 AnnotationAwareAspectJAutoProxyCreator 的父类 AbstractAutoProxyCreator 中的 postProcessBeforeInstantiation() 方法:
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
// 根据是否factoryBean(&)返回用来缓存的Bean key
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
...
}
这里的 shouldSkip() 方法的主要目的是:
- 获取所有bean的定义名称
- 遍历这些bean,找到被@Aspect标注的bean
- 通过 MetadataAwareAspectInstanceFactory 获取该bean定义中所有的 Advisor (InstantiationModelAwarePointcutAdvisorImpl )
- 最后将扫描到的增强放入缓存 advisorsCache
- advisorsCache 处于 AnnotationAwareAspectJAutoProxyCreator 的 aspectJAdvisorsBuilder 中,aspectJAdvisorsBuilder 是一个 BeanFactoryAspectJAdvisorsBuilder类型的属性。
- advisorsCache 是一个key为beanName,value为 List< Advisor > 的 ConcurrentHashMap,我们在这里构建的增强类型为 InstantiationModelAwarePointcutAdvisorImpl (Advisor 的子类),内部包含了方法名称,声明类型等细节。
经过这个过程,就能获取到我们配置的那些增强,从而在后面的过程中创建代理。
applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName)
该方法在这个处理过程中直接返回,略。
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName)
AbstractAutoProxyCreator 中的 postProcessAfterInitialization() 方法内容如下:
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 构建代理key
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
可以看到代码的最后一步调用了 wrapIfNecessary() 方法:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
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;
}
// 如果获取到增强就创建代理
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
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;
}
跳过前半部分的判断,我们来看一下后面的这个通知获取及代理的创建过程:
getAdvicesAndAdvisorsForBean() —— 获取当前bean的增强器
// AbstractAdvisorAutoProxyCreator 的 getAdvicesAndAdvisorsForBean() 方法
protected Object[] getAdvicesAndAdvisorsForBean() 方法(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
// 获取可以被当前bean使用的增强
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
可以看到 getAdvicesAndAdvisorsForBean() 方法主要是调用了 AbstractAdvisorAutoProxyCreator 的 findEligibleAdvisors() 用来获取针对当前bean的增强,方法如下:
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 获取可用增强,前面已经在resolveBeforeInstantiation()环节存到了缓存中,因此这里直接从缓存中获取
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 寻找哪些增强可以应用到当前bean上
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 添加一个增强
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
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 proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// Use original ClassLoader if bean class not locally loaded in overriding class loader
ClassLoader classLoader = getProxyClassLoader();
if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
}
// 获取代理
return proxyFactory.getProxy(classLoader);
}
由代码可见,通过createProxy() 构建代理ProxyFactory,并通过ProxyFactory构建代理:
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!NativeDetector.inNativeImage() &&
(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
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.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
从代码中我们可以知道:
- 如果指定了@EnableAspectJAutoProxy的proxyTargetClass = true,则默认使用cglib代理
- 如果是默认值(false),则在bean是接口实现的情况下选择jdk代理,否则使用cglib代理
创建代理对象后做了什么?
前面我们知道:创建代理对象后,代理对象保存在容器中。且这个对象里保存了详细的新的,如增强器,目标对象等:
接下来我们以JDK代理对象为例,通过测试方法调用,一起来看看被代理的方法是如何执行的。
当我们的测试方法被执行时,我们往被执行的方法处打一个断点,并从断点位置进去:
@Test
public void test01() {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestAspectConfig.class);
TestService bean = applicationContext.getBean(TestService.class);
bean.add(1,2);// 断点
}
add()方法是我们的代理对象TestService被增强的方法,当调用这个方法时,其实会调用代理对象的invoke()方法,代码如下:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 获取拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// 链为空
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
// 直接执行方法
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
} else {
// 创建 MethodInvocation 方法
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 调用 MethodInvocation 的 proceed() 方法
retVal = invocation.proceed();
}
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
}
获取拦截器链的过程:
-
获取所有的增强
-
将增强转换为Interceptor
-
将所有增强器转换为List< MethodInterceptor >
-
获取到拦截器链之后,传入拦截器链获取方法调用 MethodInvocation
-
调用方法,效果
-
正常执行:前置通知>目标方法>后置通知>返回通知
-
出现异常:前置通知>目标方法>后置通知>异常通知
-