@EnableAspectJAutoProxy和@Aspectj 切面 在spring容器中工作原理详解

本文深入探讨了Spring中@EnableAspectJAutoProxy注解的工作原理,揭示了它如何启动AspectJ切面在Spring容器内的注册过程。通过AspectJAutoProxyRegistrar和ImportBeanDefinitionRegistrar的交互,实现对组件的注册。接着,讲解了AbstractAutoProxyCreator、AspectJAwareAdvisorAutoProxyCreator等类的继承关系,以及它们在Bean生命周期中的作用,特别是InstantiationAwareBeanPostProcessor接口如何确保切面方法能在正确的时间点执行。通过源码分析,展示了postProcessBeforeInstantiation方法如何决定bean是否需要被切面处理,最终代理对象在调用目标方法时,如何被cglib的invoke方法拦截。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

@EnableAspectJAutoProxy
这个注解是spring启用在自己的容器中注册了一个组件

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProx

AspectJAutoProxyRegistrar就是在spring注册了这个类,这个类实现了ImportBeanDefinitionRegistrar
重写registerBeanDefinitions方法,

AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
即注册了个应该beanName为org.springframework.aop.config.internalAutoProxyCreator      对象值为AnnotationAwareAspectJAutoProxyCreator的

AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware

SmartInstantiationAwareBeanPostProcessor又实现InstantiationAwareBeanPostProcessor接口。
实现了InstantiationAwareBeanPostProcessor后置处理的接口 会再容器初始化完成bean以后执行器 后置处理器的before和after方法,BeanFactoryAware表示 其子类是可以拿到spring的 BeanFactory的,也就是所有bean的对象,不然你aspectj中怎么执行,被增强对象的 增强方法,因为增强的方法属于spring管理的对象的方法。(不是只接new 对象调用的方法)
spring的源码片段

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(String, RootBeanDefinition, Object[])
 try {	//给后置处理器一个机会返回一个目标对象的代理,这个就是给后置处理器来生成代理的方法。
		// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
		Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
		if (bean != null) {
			return bean;
		}
	}
	
	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation(String, RootBeanDefinition)
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
	Object bean = null;
	if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
		// Make sure bean class is actually resolved at this point.
		if (mbd.hasBeanClass() && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			//创建bean之前执行实现了InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法
			bean = applyBeanPostProcessorsBeforeInstantiation(mbd.getBeanClass(), beanName);
			if (bean != null) {
				//执行实现了后置处理的after方法
				bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
			}
		}
		mbd.beforeInstantiationResolved = (bean != null);
	}
	return bean;
}

那我们再看下 这个postProcessBeforeInstantiation都干啥了

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessBeforeInstantiation(Class<?>, String)
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		Object cacheKey = getCacheKey(beanClass, beanName);
		//targetSourcedBeans就是一个集合,advisedBeans标识通知的集合,nonAdvisedBeans标识不同的对象
		if (!this.targetSourcedBeans.contains(cacheKey)) {
			if (this.advisedBeans.contains(cacheKey) || this.nonAdvisedBeans.contains(cacheKey)) {
				return null;
			}
			//Advisor,Advice,AopInfrastructureBean判断父类是不是这三个类 || 含有这个Aspect注解
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				this.nonAdvisedBeans.add(cacheKey);
				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) {
			this.targetSourcedBeans.add(beanName);
			Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
			Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		return null;
	}

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(Object, String)
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    		if (bean != null) {
    			Object cacheKey = getCacheKey(bean.getClass(), beanName);
    			if (!this.earlyProxyReferences.contains(cacheKey)) {
    				return wrapIfNecessary(bean, beanName, cacheKey);
    			}
    		}
    		return bean;
    	}

//开始真正判断bean的方法是否需要被切

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
	if (this.targetSourcedBeans.contains(beanName)) {
		return bean;
	}
	if (this.nonAdvisedBeans.contains(cacheKey)) {
		return bean;
	}
	if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
		this.nonAdvisedBeans.add(cacheKey);
		return bean;
	}

	// Create proxy if we have advice.
	Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
	if (specificInterceptors != DO_NOT_PROXY) {//说明这个bean需要被切
		this.advisedBeans.add(cacheKey);
		Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));//创建代理对象
		this.proxyTypes.put(cacheKey, proxy.getClass());
		return proxy;
	}

	this.nonAdvisedBeans.add(cacheKey);
	return bean;
}

上面的getAdvicesAndAdvisorsForBean方法跟进去会调用这个方法

org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findEligibleAdvisors(Class, String)
protected List<Advisor> findEligibleAdvisors(Class beanClass, String beanName) {
		//遍历所有beanFactory中的bean查找到所有的切面,并且找到类中所有的通知方法。也就是候选的通知
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		//遍历所以所有的候选通知,看那些是能适用到当前bean中的。
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}

到这里 ,代理对象就已经创建完毕了,spring管理的是我们创建的代理对象。
当我们使用代理执行目标方法的时候,如果使用的是cglib的话,会被invoke方法拦截

org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor.intercept(Object, Method, Object[], MethodProxy)

public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
			Object oldProxy = null;
			boolean setProxyContext = false;
			Class<?> targetClass = null;
			Object target = null;
			try {
				if (this.advised.exposeProxy) {
					// Make invocation available if necessary.
					oldProxy = AopContext.setCurrentProxy(proxy);
					setProxyContext = true;
				}
				// May be null. Get as late as possible to minimize the time we
				// "own" the target, in case it comes from a pool...
				target = getTarget();
				if (target != null) {
					targetClass = target.getClass();
				}
				//获取这个对象目标方法所有适配的通知方法。
				List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); //--》》////getInterceptorsAndDynamicInterceptionAdvice()---》getInterceptorsAndDynamicInterceptionAdvice
				Object retVal;
				// Check whether we only have one InvokerInterceptor: that is,
				// no real advice, but just reflective invocation of the target.
				if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
					// We can skip creating a MethodInvocation: just invoke the target directly.
					// Note that the final invoker must be an InvokerInterceptor, so we know
					// it does nothing but a reflective operation on the target, and no hot
					// swapping or fancy proxying.
					Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
					retVal = methodProxy.invoke(target, argsToUse);
				}
				else {
					// We need to create a method invocation...
					//调用目标方法,并且会从spring容器中寻找通知方法类所对应的对象,同时调用通知方法。
					retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
				}
				retVal = processReturnType(proxy, target, method, retVal);
				return retVal;
			}
			finally {
				if (target != null) {
					releaseTarget(target);
				}
				if (setProxyContext) {
					// Restore old proxy.
					AopContext.setCurrentProxy(oldProxy);
				}
			}
		}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值