else {
return super.sortAdvisors(advisors);
}
}
这里排序主要是委托给PartialOrder进行的,而在此之前将所有的切面都封装成了PartiallyComparableAdvisorHolder对象,注意传入的DEFAULT_PRECEDENCE_COMPARATOR参数,这个就是比较器对象:
private static final Comparator DEFAULT_PRECEDENCE_COMPARATOR = new AspectJPrecedenceComparator();
所以我们直接看这个比较器的compare方法:
public int compare(Advisor o1, Advisor o2) {
int advisorPrecedence = this.advisorComparator.compare(o1, o2);
if (advisorPrecedence == SAME_PRECEDENCE && declaredInSameAspect(o1, o2)) {
advisorPrecedence = comparePrecedenceWithinAspect(o1, o2);
}
return advisorPrecedence;
}
private final Comparator super Advisor> advisorComparator;
public AspectJPrecedenceComparator() {
this.advisorComparator = AnnotationAwareOrderComparator.INSTANCE;
}
第一步先通过AnnotationAwareOrderComparator去比较,点进去看可以发现是对实现了PriorityOrdered和Ordered接口以及标记了Priority和Order注解的非同一个@Aspect类中的切面进行排序。这个和之前分析BeanFacotryPostProcessor类是一样的原理。而对同一个@Aspect类中的切面排序主要是comparePrecedenceWithinAspect方法:
private int comparePrecedenceWithinAspect(Advisor advisor1, Advisor advisor2) {
boolean oneOrOtherIsAfterAdvice =
(AspectJAopUtils.isAfterAdvice(advisor1) || AspectJAopUtils.isAfterAdvice(advisor2));
int adviceDeclarationOrderDelta = getAspectDeclarationOrder(advisor1) - getAspectDeclarationOrder(advisor2);
if (oneOrOtherIsAfterAdvice) {
// the advice declared last has higher precedence
if (adviceDeclarationOrderDelta < 0) {
// advice1 was declared before advice2
// so advice1 has lower precedence
return LOWER_PRECEDENCE;
}
else if (adviceDeclarationOrderDelta == 0) {
return SAME_PRECEDENCE;
}
else {
return HIGHER_PRECEDENCE;
}
}
else {
// the advice declared first has higher precedence
if (adviceDeclarationOrderDelta < 0) {
// advice1 was declared before advice2
// so advice1 has higher precedence
return HIGHER_PRECEDENCE;
}
else if (adviceDeclarationOrderDelta == 0) {
return SAME_PRECEDENCE;
}
else {
return LOWER_PRECEDENCE;
}
}
}
private int getAspectDeclarationOrder(Advisor anAdvisor) {
AspectJPrecedenceInformation precedenceInfo =
AspectJAopUtils.getAspectJPrecedenceInformationFor(anAdvisor);
if (precedenceInfo != null) {
return precedenceInfo.getDeclarationOrder();
}
else {
return 0;
}
}
这里就是通过precedenceInfo.getDeclarationOrder拿到在创建InstantiationModelAwarePointcutAdvisorImpl对象时设置的declarationOrder属性,这就验证了之前的说法(实际上这里排序过程非常复杂,不是简单的按照这个属性进行排序)。
当上面的一切都进行完成后,就该创建代理对象了,回到AbstractAutoProxyCreator.wrapIfNecessary,看关键部分代码:
//如果有切面,则生成该bean的代理
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//把被代理对象bean实例封装到SingletonTargetSource对象中
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
注意这里将被代理对象封装成了一个SingletonTargetSource对象,它是TargetSource的实现类。
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 = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
//proxyTargetClass 是否对类进行代理,而不是对接口进行代理,设置为true时,使用CGLib代理。
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
//把advice类型的增强包装成advisor切面
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
用来控制代理工厂被配置后,是否还允许修改代理的配置,默认为false
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//获取代理实例
return proxyFactory.getProxy(getProxyClassLoader());
}
这里通过ProxyFactory对象去创建代理实例,这是工厂模式的体现,但在创建代理对象之前还有几个准备动作:需要判断是JDK代理还是CGLIB代理以及通过buildAdvisors方法将扩展的Advice封装成Advisor切面。准备完成则通过getProxy创建代理对象:
public Object getProxy(@Nullable ClassLoader classLoader) {
//根据目标对象是否有接口来判断采用什么代理方式,cglib代理还是jdk动态代理
return createAopProxy().getProxy(classLoader);
}
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (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);
}
}
首先通过配置拿到对应的代理类:ObjenesisCglibAopProxy和JdkDynamicAopProxy,然后再通过getProxy创建Bean的代理,这里以JdkDynamicAopProxy为例:
public Object getProxy(@Nullable ClassLoader classLoader) {
//advised是代理工厂对象
Class>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
这里的代码你应该不陌生了,就是JDK的原生API,newProxyInstance方法传入的InvocationHandler对象是this,因此,最终AOP代理的调用就是从该类中的invoke方法开始。至此,代理对象的创建就完成了,下面来看下整个过程的时序图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g4ND5aLn-1651141896602)(https://upload-images.jianshu.io/uplo 《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 ad_images/13465705-bb55fefd180016fd?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]
小结代理对象的创建过程整体来说并不复杂,首先找到所有带有@Aspect注解的类,并获取其中没有@Pointcut注解的方法,循环创建切面,而创建切面需要切点和增强两个元素,其中切点可简单理解为我们写的表达式,增强则是根据@Before、@Around、@After等注解创建的对应的Advice类。切面创建好后则需要循环判断哪些切面能对当前的Bean实例的方法进行增强并排序,最后通过ProxyFactory创建代理对象。
AOP链式调用熟悉JDK动态代理的都知道通过代理对象调用方法时,会进入到InvocationHandler对象的invoke方法,所以我们直接从JdkDynamicAopProxy的这个方法开始:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
//从代理工厂中拿到TargetSource对象,该对象包装了被代理实例bean
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
//被代理对象的equals方法和hashCode方法是不能被代理的,不会走切面
…
Object retVal;
// 可以从当前线程中拿到代理对象
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
//这个target就是被代理实例
target = targetSource.getTarget();
Class> targetClass = (target != null ? target.getClass() : null);
//从代理工厂中拿过滤器链 Object是一个MethodInterceptor类型的对象,其实就是一个advice对象
List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
//如果该方法没有执行链,则说明这个方法不需要被拦截,则直接反射调用
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();
}
// Massage return value if necessary.
Class> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
retVal = proxy;
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
这段代码比较长,我删掉了不关键的地方。首先来看this.advised.exposeProxy这个属性,这在@EnableAspectJAutoProxy注解中可以配置,当为true时,会将该代理对象设置到当前线程的ThreadLocal对象中,这样就可以通过AopContext.currentProxy拿到代理对象。这个有什么用呢?我相信有经验的Java开发都遇到过这样一个BUG,在Service实现类中调用本类中的另一个方法时,事务不会生效,这是因为直接通过this调用就不会调用到代理对象的方法,而是原对象的,所以事务切面就没有生效。因此这种情况下就可以从当前线程的ThreadLocal对象拿到代理对象,不过实际上直接使用@Autowired注入自己本身也可以拿到代理对象。
接下来就是通过getInterceptorsAndDynamicInterceptionAdvice拿到执行链,看看具体做了哪些事情:
public List getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class> targetClass) {
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
//从代理工厂中获得该被代理类的所有切面advisor,config就是代理工厂对象
Advisor[] advisors = config.getAdvisors();
List interceptorList = new ArrayList<>(advisors.length);
Class> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
Boolean hasIntroductions = null;
for (Advisor advisor : advisors) {
//大部分走这里
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
//如果切面的pointCut和被代理对象是匹配的,说明是切面要拦截的对象
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
if (mm instanceof IntroductionAwareMethodMatcher) {
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
}
else {
//接下来判断方法是否是切面pointcut需要拦截的方法
match = mm.matches(method, actualClass);
}
//如果类和方法都匹配
if (match) {
//获取到切面advisor中的advice,并且包装成MethodInterceptor类型的对象
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
//如果是引介切面
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
这也是个长方法,看关键的部分,因为之前我们创建的基本上都是InstantiationModelAwarePointcutAdvisorImpl对象,该类是PointcutAdvisor的实现类,所以会进入第一个if判断里,这里首先进行匹配,看切点和当前对象以及该对象的哪些方法匹配,如果能匹配上,则调用getInterceptors获取执行链:
private final List adapters = new ArrayList<>(3);
public DefaultAdvisorAdapterRegistry() {
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List interceptors = new ArrayList<>(3);
Advice advice = advisor.getAdvice();
//如果是MethodInterceptor类型的,如:AspectJAroundAdvice
//AspectJAfterAdvice
//AspectJAfterThrowingAdvice
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
//处理 AspectJMethodBeforeAdvice AspectJAfterReturningAdvice
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[0]);
}
这里我们可以看到如果是MethodInterceptor的实现类,则直接添加到链中,如果不是,则需要通过适配器去包装后添加,刚好这里有MethodBeforeAdviceAdapter和AfterReturningAdviceAdapter两个适配器对应上文两个没有实现MethodInterceptor接口的类。最后将Interceptors返回。
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// We need to create a method invocation…
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
}
返回到invoke方法后,如果执行链为空,说明该方法不需要被增强,所以直接反射调用原对象的方法(注意传入的是TargetSource封装的被代理对象);反之,则通过ReflectiveMethodInvocation类进行链式调用,关键方法就是proceed:
private int currentInterceptorIndex = -1;
public Object proceed() throws Throwable {
//如果执行链中的advice全部执行完,则直接调用joinPoint方法,就是被代理方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
return proceed();
}
}
else {
//调用MethodInterceptor中的invoke方法
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
这个方法的核心就在两个地方:invokeJoinpoint和interceptorOrInterceptionAdvice.invoke(this)。当增强方法调用完后就会通过前者调用到被代理的方法,否则则是依次调用Interceptor的invoke方法。下面就分别看看每个Interceptor是怎么实现的。
- AspectJAroundAdvice
public Object invoke(MethodInvocation mi) throws Throwable {
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
JoinPointMatch jpm = getJoinPointMatch(pmi);
return invokeAdviceMethod(pjp, jpm, null, null);
}
- MethodBeforeAdviceInterceptor -> AspectJMethodBeforeAdvice
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
- AspectJAfterAdvice
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
finally {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
- AfterReturningAdviceInterceptor -> AspectJAfterReturningAdvice
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
public void afterReturning(@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target) throws Throwable {
if (shouldInvokeOnReturnValueOf(method, returnValue)) {
invokeAdviceMethod(getJoinPointMatch(), returnValue, null);
}
}
- AspectJAfterThrowingAdvice
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
catch (Throwable ex) {
if (shouldInvokeOnThrowing(ex)) {
invokeAdviceMethod(getJoinPointMatch(), null, ex);
}
throw ex;
}
}
这里的调用顺序是怎样的呢?其核心就是通过proceed方法控制流程,每执行完一个Advice就会回到proceed方法中调用下一个Advice。可以思考一下,怎么才能让调用结果满足如下图的执行顺序。
以上就是AOP的链式调用过程,但是这只是只有一个切面类的情况,如果有多个@Aspect类呢,这个调用过程又是怎样的?其核心思想和“栈”一样,就是“先进后出,后进先出”。
AOP扩展知识 一、自定义全局拦截器Interceptor在上文创建代理对象的时候有这样一个方法:
protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
//自定义MethodInterceptor.拿到setInterceptorNames方法注入的Interceptor对象
Advisor[] commonInterceptors = resolveInterceptorNames();
List allInterceptors = new ArrayList<>();
if (specificInterceptors != null) {
allInterceptors.addAll(Arrays.asList(specificInterceptors));
if (commonInterceptors.length > 0) {
if (this.applyCommonInterceptorsFirst) {
allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
}
else {
allInterceptors.addAll(Arrays.asList(commonInterceptors));
}
}
}
Advisor[] advisors = new Advisor[allInterceptors.size()];
for (int i = 0; i < allInterceptors.size(); i++) {
//对自定义的advice要进行包装,把advice包装成advisor对象,切面对象
advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
}
return advisors;
}
这个方法的作用就在于我们可以扩展我们自己的Interceptor,首先通过resolveInterceptorNames方法获取到通过setInterceptorNames方法设置的Interceptor,然后调用DefaultAdvisorAdapterRegistry.wrap方法将其包装为DefaultPointcutAdvisor对象并返回:
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
Advice advice = (Advice) adviceObject;
if (advice instanceof MethodInterceptor) {
return new DefaultPointcutAdvisor(advice);
}
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
throw new UnknownAdviceTypeException(advice);
}
public DefaultPointcutAdvisor(Advice advice) {
this(Pointcut.TRUE, advice);
}
需要注意DefaultPointcutAdvisor构造器里面传入了一个Pointcut.TRUE,表示这种扩展的Interceptor是全局的拦截器。下面来看看如何使用:
public class MyMethodInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println(“自定义拦截器”);
return invocation.proceed();
}
}
首先写一个类实现MethodInterceptor 接口,在invoke方法中实现我们的拦截逻辑,然后通过下面的方式测试,只要UserService 有AOP拦截就会发现自定义的MyMethodInterceptor也生效了。
public void costomInterceptorTest() {
AnnotationAwareAspectJAutoProxyCreator bean = applicationContext.getBean(AnnotationAwareAspectJAutoProxyCreator.class);
bean.setInterceptorNames("myMethodInterceptor ");
UserService userService = applicationContext.getBean(UserService.class);
userService.queryUser(“dark”);
}
但是如果换个顺序,像下面这样:
public void costomInterceptorTest() {
UserService userService = applicationContext.getBean(UserService.class);
AnnotationAwareAspectJAutoProxyCreator bean = applicationContext.getBean(AnnotationAwareAspectJAutoProxyCreator.class);
bean.setInterceptorNames("myMethodInterceptor ");
userService.queryUser(“dark”);
}
这时自定义的全局拦截器就没有作用了,这是为什么呢?因为当执行getBean的时候,如果有切面匹配就会通过ProxyFactory去创建代理对象,注意Interceptor是存到这个Factory对象中的,而这个对象和代理对象是一一对应的,因此调用getBean时,还没有myMethodInterceptor这个对象,自定义拦截器就没有效果了,也就是说要想自定义拦截器生效,就必须在代理对象生成之前注册进去。
二、循环依赖三级缓存存在的必要性在上一篇文章我分析了Spring是如何通过三级缓存来解决循环依赖的问题的,但你是否考虑过第三级缓存为什么要存在?我直接将bean存到二级不就行了么,为什么还要存一个ObjectFactory对象到第三级缓存中?这个在学习了AOP之后就很清楚了,因为我们在@Autowired对象时,想要注入的不一定是Bean本身,而是想要注入一个修改过后的对象,如代理对象。在AbstractAutowireCapableBeanFactory.getEarlyBeanReference方法中循环调用了SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference方法,AbstractAutoProxyCreator对象就实现了该方法:
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
this.earlyProxyReferences.add(cacheKey);
}
// 创建代理对象
return wrapIfNecessary(bean, beanName, cacheKey);
}
因此,当我们想要对循坏依赖的Bean做出修改时,就可以像AOP这样做。
三、如何在Bean创建之前提前创建代理对象Spring的代理对象基本上都是在Bean实例化完成之后创建的,但在文章开始我就说过,Spring也提供了一个机会在创建Bean对象之前就创建代理对象,在AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation方法中:
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.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
protected Object applyBeanPostProcessorsBeforeInstantiation(Class> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
主要是InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation方法中,这里又会进入到AbstractAutoProxyCreator类中:
public Object postProcessBeforeInstantiation(Class> beanClass, String beanName) {
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
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;
}
protected TargetSource getCustomTargetSource(Class> beanClass, String beanName) {
// We can’t create fancy target sources for directly registered singletons.
if (this.customTargetSourceCreators != null &&
this.beanFactory != null && this.beanFactory.containsBean(beanName)) {
for (TargetSourceCreator tsc : this.customTargetSourceCreators) {
TargetSource ts = tsc.getTargetSource(beanClass, beanName);
if (ts != null) {
return ts;
}
}
}
// No custom TargetSource found.
return null;
}
看到这里大致应该明白了,先是获取到一个自定义的TargetSource对象,然后创建代理对象,所以我们首先需要自己实现一个TargetSource类,这里直接继承一个抽象类,getTarget方法则返回原始对象:
public class MyTargetSource extends AbstractBeanFactoryBasedTargetSource {
@Override
public Object getTarget() throws Exception {
return getBeanFactory().getBean(getTargetBeanName());
}
}
但这还不够,上面首先判断了customTargetSourceCreators!=null,而这个属性是个数组,可以通过下面这个方法设置进来:
public void setCustomTargetSourceCreators(TargetSourceCreator… targetSourceCreators) {
this.customTargetSourceCreators = targetSourceCreators;
}
所以我们还要实现一个TargetSourceCreator类,同样继承一个抽象类实现,并只对userServiceImpl对象进行拦截:
public class MyTargetSourceCreator extends AbstractBeanFactoryBasedTargetSourceCreator {
@Override
protected AbstractBeanFactoryBasedTargetSource createBeanFactoryBasedTargetSource(Class> beanClass, String beanName) {
if (getBeanFactory() instanceof ConfigurableListableBeanFactory) {
if(beanName.equalsIgnoreCase(“userServiceImpl”)) {
return new MyTargetSource();
}
}
return null;
}
}
createBeanFactoryBasedTargetSource方法是在AbstractBeanFactoryBasedTargetSourceCreator.getTargetSource中调用的,而getTargetSource就是在上面getCustomTargetSource中调用的。以上工作做完后,还需要将其设置到AnnotationAwareAspectJAutoProxyCreator对象中,因此需要我们注入这个对象:
@Configuration
public class TargetSourceCreatorBean {
@Autowired
private BeanFactory beanFactory;
@Bean
public AnnotationAwareAspectJAutoProxyCreator annotationAwareAspectJAutoProxyCreator() {
AnnotationAwareAspectJAutoProxyCreator creator = new AnnotationAwareAspectJAutoProxyCreator();
MyTargetSourceCreator myTargetSourceCreator = new MyTargetSourceCreator();
myTargetSourceCreator.setBeanFactory(beanFactory);
creator.setCustomTargetSourceCreators(myTargetSourceCreator);
return creator;
}
}
这样,当我们通过getBean获取userServiceImpl的对象时,就会优先生成代理对象,然后在调用执行链的过程中再通过TargetSource.getTarget获取到被代理对象。但是,为什么我们在getTarget方法中调用getBean就能拿到被代理对象呢?
继续探究,通过断点我发现从getTarget进入时,在resolveBeforeInstantiation方法中返回的bean就是null了,而getBeanPostProcessors方法返回的Processors中也没有了AnnotationAwareAspectJAutoProxyCreator对象,也就是没有进入到AbstractAutoProxyCreator.postProcessBeforeInstantiation方法中,所以不会再次获取到代理对象,那AnnotationAwareAspectJAutoProxyCreator对象是在什么时候移除的呢?
带着问题,我开始反推,发现在AbstractBeanFactoryBasedTargetSourceCreator类中有这样一个方法buildInternalBeanFactory:
protected DefaultListableBeanFactory buildInternalBeanFactory(ConfigurableBeanFactory containingFactory) {
DefaultListableBeanFactory internalBeanFactory = new DefaultListableBeanFactory(containingFactory);
eImpl的对象时,就会优先生成代理对象,然后在调用执行链的过程中再通过TargetSource.getTarget获取到被代理对象。但是,为什么我们在getTarget方法中调用getBean就能拿到被代理对象呢?
继续探究,通过断点我发现从getTarget进入时,在resolveBeforeInstantiation方法中返回的bean就是null了,而getBeanPostProcessors方法返回的Processors中也没有了AnnotationAwareAspectJAutoProxyCreator对象,也就是没有进入到AbstractAutoProxyCreator.postProcessBeforeInstantiation方法中,所以不会再次获取到代理对象,那AnnotationAwareAspectJAutoProxyCreator对象是在什么时候移除的呢?
带着问题,我开始反推,发现在AbstractBeanFactoryBasedTargetSourceCreator类中有这样一个方法buildInternalBeanFactory**:
protected DefaultListableBeanFactory buildInternalBeanFactory(ConfigurableBeanFactory containingFactory) {
DefaultListableBeanFactory internalBeanFactory = new DefaultListableBeanFactory(containingFactory);



