目录
1. 前言
上一篇文章已经讲解过AOP责任链的实现原理(Spring之AOP的实现),这一篇文章主要讲解AOP中代理对象创建的时机,普通的IOC对象的创建流程见:Spring依赖注入(DI)之注解形式
2.动态代理对象创建的时机
我们回到Bean的创建过程,主要看AbstractAutowireCapableBeanFactory的doCreateBean方法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
//省略部分代码
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
//初始化bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
}
//省略部分代码
return exposedObject;
}
主要是看initializeBean方法
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
//后置处理器
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
AbstractAutowireCapableBeanFactory中的applyBeanPostProcessorsAfterInitialization方法,如下:
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
//调用其postProcessAfterInitialization
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
这里会有AnnotationAwareAspectJAutoProxyCreator它是专门用于生成AOP代理对象的处理器
但是AnnotationAwareAspectJAutoProxyCreator中并没有postProcessAfterInitialization方法,而是它的父父父类AbstractAutoProxyCreator中实现的,我们看看这个方法:
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
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;
}
// Create proxy if we have advice.
//获得是否有增强
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方法先获取是否有增强,我们这里是有做around增强,我们看看这个方法:
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
调用了findEligibleAdvisors方法获取是否有增强
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors();
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
这里调用的是findCandidateAdvisors方法
@Override
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
这个时候aspectJAdvisorsBuilder其实就是我们的LogAspect,buildAspectJAdvisors方法如下:
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;
//省略部分代码
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
List<Advisor> advisors = new ArrayList<>();
for (String aspectName : aspectNames) {
//获得的是logAround
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
}
else {
MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
所以这里获得的是LogAspect中的logAround
这个时候回到了AbstractAdvisorAutoProxyCreator的findEligibleAdvisors方法中,会继续调用extendAdvisors方法,如下:
@Override
protected void extendAdvisors(List<Advisor> candidateAdvisors) {
AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
}
看,惊喜不,看方法名业知道是要在代理链上增加一个特殊的advisor,我们来看看这个方法:
public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
// Don't add advisors to an empty list; may indicate that proxying is just not required
if (!advisors.isEmpty()) {
boolean foundAspectJAdvice = false;
for (Advisor advisor : advisors) {
// Be careful not to get the Advice without a guard, as this might eagerly
// instantiate a non-singleton AspectJ aspect...
if (isAspectJAdvice(advisor)) {
foundAspectJAdvice = true;
break;
}
}
if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
//把ExposeInvocationInterceptor增加到第一个
advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
return true;
}
}
return false;
}
看我们往advisors中增加了 ExposeInvocationInterceptor对象,放入到第一个元素,这个时候chain一共是有2个元素,如下所示:
我们再回到findEligibleAdvisors方法,增加了ExposeInvocationInterceptor之后,会调用sortAdvisors方法进行拦截器的排序,这里的排序涉及到责任链的顺序问题,先不展开,后面会详细讲到,这里只要知道排序后ExposeInvocationInterceptor会在第一个,然后就返回了Advisor列表,这时候只有两个元素。
我们就回到了AbstractAdvisorAutoProxyCreator的getAdvicesAndAdvisorsForBean方法中,如下:
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
如果增强列表为空,则返回一个null,表示不需要进行代理。这里我们知道返回的是有2个增强的持有增强列表。
然后我们再回到AbstractAutoProxyCreator的 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;
}
// Create proxy if we have advice.
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;
}
我们知道,我们获取到特定的增强拦截器不为DO_NOT_PROXY,则会调用createProxy方法去创建代理对象proxy,最终则返回这个代理对象。我们来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 = 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);
}
//创建代理对象
return proxyFactory.getProxy(getProxyClassLoader());
}
我们主要看最后一行代码,getProxy方法得到代理对象
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
我们先看createAopProxy()方法,这个就是创建一个AopProxy对象,然后去调用它的getProxy方法得到代理对象,createAopProxy方法如下:
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
这里的getAopProxyFactory获取到的是DefaultAopProxyFactory对象,我们来看看它的createAopProxy方法
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
//optimize为true或者proxyTargetClass为ture或者是没有实现
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)) {
//使用jdk动态代理
return new JdkDynamicAopProxy(config);
}
//使用cglib动态代理
return new ObjenesisCglibAopProxy(config);
}
else {
//使用jdk动态代理
return new JdkDynamicAopProxy(config);
}
}
可以看到,根据不同的规则去选择使用JDK动态代理还是使用CGLIB动态代理,因为我们这里本身有实现接口,且proxy-target-class: false设置为false,则使用的是JDK动态代理,即生成了JdkDynamicAopProxy对象。
然后需要调用其getProxy方法
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
可以看到,这里是调用了Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);方法去创建代理对象,需要注意的是第三个参数,传递的是this,因为JdkDynamicAopProxy本身实现了InvocationHandler接口,这就是上一章中讲到的Spring之AOP的实现_旭日的芬芳-CSDN博客,为什么在目标方法调用之前会先回调JdkDynamicAopProxy的invoke方法。
如果是CGLIB的动态代理呢?我们来看看CglibAopProxy中getProxy方法
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
}
try {
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
Class<?> proxySuperClass = rootClass;
if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
// Validate the class, writing log messages as necessary.
validateClassIfNecessary(proxySuperClass, classLoader);
// Configure CGLIB Enhancer...
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
//得到callback回调
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call above
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// Generate the proxy class and create a proxy instance.
//创建代理对象
return createProxyClassAndInstance(enhancer, callbacks);
}
catch (CodeGenerationException | IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
": Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Throwable ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
我们先看getCallbacks方法,这个方法里会包装拦截器,如下:
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
// Parameters used for optimization choices...
boolean exposeProxy = this.advised.isExposeProxy();
boolean isFrozen = this.advised.isFrozen();
boolean isStatic = this.advised.getTargetSource().isStatic();
// Choose an "aop" interceptor (used for AOP calls).
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
// Choose a "straight to target" interceptor. (used for calls that are
// unadvised but can return this). May be required to expose the proxy.
Callback targetInterceptor;
if (exposeProxy) {
targetInterceptor = (isStatic ?
new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
}
else {
targetInterceptor = (isStatic ?
new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
}
// Choose a "direct to target" dispatcher (used for
// unadvised calls to static targets that cannot return this).
Callback targetDispatcher = (isStatic ?
new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());
Callback[] mainCallbacks = new Callback[] {
//AOP的拦截器
aopInterceptor, // for normal advice
targetInterceptor, // invoke target without considering advice, if optimized
new SerializableNoOp(), // no override for methods mapped to this
targetDispatcher, this.advisedDispatcher,
new EqualsInterceptor(this.advised),
new HashCodeInterceptor(this.advised)
};
Callback[] callbacks;
// If the target is a static one and the advice chain is frozen,
// then we can make some optimizations by sending the AOP calls
// direct to the target using the fixed chain for that method.
if (isStatic && isFrozen) {
Method[] methods = rootClass.getMethods();
Callback[] fixedCallbacks = new Callback[methods.length];
this.fixedInterceptorMap = new HashMap<>(methods.length);
// TODO: small memory optimization here (can skip creation for methods with no advice)
for (int x = 0; x < methods.length; x++) {
Method method = methods[x];
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
this.fixedInterceptorMap.put(method, x);
}
// Now copy both the callbacks from mainCallbacks
// and fixedCallbacks into the callbacks array.
callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
this.fixedInterceptorOffset = mainCallbacks.length;
}
else {
callbacks = mainCallbacks;
}
return callbacks;
}
我们主要是关心下面这个拦截器,它是用于普通的aop增强的拦截
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
这个对象不就是上一章中我们讲到的CGLIB动态实现中的回调类么?在获取到拦截器后,再调用了createProxyClassAndInstance方法去创建代理类。方法如下:
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
enhancer.setInterceptDuringConstruction(false);
enhancer.setCallbacks(callbacks);
return (this.constructorArgs != null && this.constructorArgTypes != null ?
enhancer.create(this.constructorArgTypes, this.constructorArgs) :
enhancer.create());
}
可以看到,就是通过Enhancer的setCallback去设置回调,并调用它的create方法去创建代理对象。
这个时候,代理对象就创建出来了。我们再回到AbstractAutoProxyCreator的wrapIfNecessary方法,然后一步一步返回这个代理对象就回到了AbstractAutowireCapableBeanFactory的doCreateBean方法
exposedObject = initializeBean(beanName, exposedObject, mbd);
这个时候,exposedObject就是一个代理对象了,我们继续往下看,会调用addSingleton方法,把创建的代理对象放入到内存缓存singletonObjects中
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
这样,IOC容器就帮我们创建了一个代理对象,并存入到了singletonObjects中,它的key是AOPTestController,它的值是一个通过JDK动态代理生成的代理对象。如下:
3.循环依赖
我们在上一章Spring依赖注入(DI)之注解形式_旭日的芬芳-CSDN博客最后有讲到IOC循环依赖的问题,有用到三级缓存,但是为什么是三级缓存而不是两级缓存呢?(1个半成品的bean,1成品的bean)
我们先回顾下之前的三级缓存:
//一级缓存,成品bean
Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
//二级缓存,半成品bean
Map<String, Object> earlySingletonObjects = new HashMap<>(16);
//三级缓存, bean工厂
Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
其实,如果不考虑AOP的机制,通过二级缓存是可以解决循环依赖的问题的,如下:
可以看到,只要我们在创建a以后,把这个半成品放入二级缓存中,再在给b属性a复制时,从二级缓存中获取到a,就能完成b的创建,进而完成a的创建。
但如果我们a对象是一个代理对象,这个时候机制就不一样了,当给b属性赋值时,理论上是需要给它赋值一个a的代理对象,而从二级缓存中获取到的是a对象本身,这样就起不到代理作用了。
这也就是三级缓存的意义,如下图:
也就是完成A对象实例化后,把A的Bean工厂放到三级缓存中,当需要为b的属性a赋值时,是从三级缓存中拿到A的Bean工厂,创建A的代理对象,把A的代理对象放入到二级缓存中,并返回用于初始化b中的a属性。
所以,三级缓存的作用就是解决AOP中的循环依赖,把生成代理对象的过程提前了。
4.AOP责任链的先后顺序
再回到findEligibleAdvisors方法,增加了ExposeInvocationInterceptor之后,会调用sortAdvisors方法进行拦截器的排序,而这个方法是由它的子类AspectJAwareAdvisorAutoProxyCreator来实现的,我们来看看这个方法:
@Override
@SuppressWarnings("unchecked")
protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
List<PartiallyComparableAdvisorHolder> partiallyComparableAdvisors = new ArrayList<>(advisors.size());
for (Advisor element : advisors) {
partiallyComparableAdvisors.add(
new PartiallyComparableAdvisorHolder(element, DEFAULT_PRECEDENCE_COMPARATOR));
}
List<PartiallyComparableAdvisorHolder> sorted = PartialOrder.sort(partiallyComparableAdvisors);
if (sorted != null) {
List<Advisor> result = new ArrayList<>(advisors.size());
for (PartiallyComparableAdvisorHolder pcAdvisor : sorted) {
result.add(pcAdvisor.getAdvisor());
}
return result;
}
else {
return super.sortAdvisors(advisors);
}
}
这里是使用AspectJPrecedenceComparator对象来创建了一个PartiallyComparableAdvisorHolder对象来进行比较,我们来看看这个比较器的compare方法:
@Override
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;
}
可以看到,先是调用advisorComparator的compare方法进行比较,如果比较出来是相同的优先级且声明在相同的切面里,则调用comparePrecedenceWithinAspect中继续比较。
我们先看advisorComparator的compare,advisorComparator是一个AnnotationAwareOrderComparator对象,但它并没有实现compare方法,而需要看它的父类OrderComparator,我来看看该方法
public int compare(@Nullable Object o1, @Nullable Object o2) {
return this.doCompare(o1, o2, (OrderComparator.OrderSourceProvider)null);
}
private int doCompare(@Nullable Object o1, @Nullable Object o2, @Nullable OrderComparator.OrderSourceProvider sourceProvider) {
boolean p1 = o1 instanceof PriorityOrdered;
boolean p2 = o2 instanceof PriorityOrdered;
if (p1 && !p2) {
return -1;
} else if (p2 && !p1) {
return 1;
} else {
int i1 = this.getOrder(o1, sourceProvider);
int i2 = this.getOrder(o2, sourceProvider);
return Integer.compare(i1, i2);
}
}
这里会先判断比较的对象是否实现PriorityOrdered接口,这里都没有实现,则会分别调用getOrder方法去获取order的值,
private int getOrder(@Nullable Object obj, @Nullable OrderSourceProvider sourceProvider) {
Integer order = null;
if (obj != null && sourceProvider != null) {
Object orderSource = sourceProvider.getOrderSource(obj);
if (orderSource != null) {
if (orderSource.getClass().isArray()) {
Object[] sources = ObjectUtils.toObjectArray(orderSource);
for (Object source : sources) {
order = findOrder(source);
if (order != null) {
break;
}
}
}
else {
order = findOrder(orderSource);
}
}
}
return (order != null ? order : getOrder(obj));
}
这里会调用getOrder方法
protected int getOrder(@Nullable Object obj) {
if (obj != null) {
Integer order = findOrder(obj);
if (order != null) {
return order;
}
}
return Ordered.LOWEST_PRECEDENCE;
}
而在getOrder方法中会调用findOrder方法获取order,如果没有获取到则返回最低的优先级,这里findOrder实际调用的是子类AnnotationAwareOrderComparator的findOrder方法
@Override
@Nullable
protected Integer findOrder(Object obj) {
Integer order = super.findOrder(obj);
if (order != null) {
return order;
}
return findOrderFromAnnotation(obj);
}
这里是先调用父类的findOrder方法,如下:
@Nullable
protected Integer findOrder(Object obj) {
return obj instanceof Ordered ? ((Ordered)obj).getOrder() : null;
}
如果实现了Ordered接口,则调用getOrder得到order,如果没有则返回null,我们自定义的切面增强其实是属于InstantiationModelAwarePointcutAdvisorImpl实体,下面是它的定义:
final class InstantiationModelAwarePointcutAdvisorImpl
implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation, Serializable {
而AspectJPrecedenceInformation就是一个继承于Ordered的接口,定义如下:
public interface AspectJPrecedenceInformation extends Ordered {
所以我们的环绕增强,其实也是属于Ordered,所以会调用它的getOrder方法,但不管怎么样,最后会调用到OrderUtils中的getOrder方法
public static int getOrder(Class<?> type, int defaultOrder) {
Integer order = getOrder(type);
return (order != null ? order : defaultOrder);
}
会先调用getOrder方法,这里返回的为null,则是给定的默认排序,这里默认的排序是Integer的最大值,因为order定义为Integer,其实这里就是最低优先级
int LOWEST_PRECEDENCE = Integer.MAX_VALUE;
我们再回到AnnotationAwareOrderComparator的findOrder方法,这个时候order就有值了,然后我们再看ExposeInvocationInterceptor,它本身实现了PriorityOrdered(是Ordered接口的子接口)接口,并且实现了getOrder方法
@Override
public int getOrder() {
return PriorityOrdered.HIGHEST_PRECEDENCE + 1;
}
而HIGHEST_PRECEDENCE是在Ordered中定义的,表示最高优先级
public interface Ordered {
int HIGHEST_PRECEDENCE = -2147483648;
int LOWEST_PRECEDENCE = 2147483647;
int getOrder();
}
这也是为什么ExposeInvocationInterceptor会排序到最前面的原因,我们回到AspectJPrecedenceComparator的compare方法
@Override
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;
}
这个时候advisorPrecedence=1,即环绕增强的优先级更低,如下图所示:
这个如果是两个没有实现Ordered接口或者实现了Ordered接口但是返回的order一致的情况下,
比如我们自己定义的切面,没有实现Ordered接口,则这里返回了null,则
核心方法是在comparePrecedenceWithinAspect中,会先判断是否是后置增强,如果是后置增强,则越晚声明权限越高,否则越早声明权限越高。
是直接调用的AnnotationAwareOrderComparator.sort方法进行排序,方法如下:
public static void sort(List<?> list) {
if (list.size() > 1) {
list.sort(INSTANCE);
}
}
这里传入的是AnnotationAwareOrderComparator的实例,我们来看看它的findOrder方法
@Nullable
protected Integer findOrder(Object obj) {
Integer order = super.findOrder(obj);
return order != null ? order : this.findOrderFromAnnotation(obj);
}
@Nullable
private Integer findOrderFromAnnotation(Object obj) {
AnnotatedElement element = obj instanceof AnnotatedElement ? (AnnotatedElement)obj : obj.getClass();
MergedAnnotations annotations = MergedAnnotations.from((AnnotatedElement)element, SearchStrategy.TYPE_HIERARCHY);
Integer order = OrderUtils.getOrderFromAnnotations((AnnotatedElement)element, annotations);
return order == null && obj instanceof DecoratingProxy ? this.findOrderFromAnnotation(((DecoratingProxy)obj).getDecoratedClass()) : order;
}
会先调用super.findOrder方法,调用的是OrderComparator的findOrder方法,下面是这个类的源码
@Nullable
protected Integer findOrder(Object obj) {
return obj instanceof Ordered ? ((Ordered)obj).getOrder() : null;
}
这里就是判断我们的切面是否实现了Ordered接口,如果实现了,则直接调用其getOrder得到排序的循序。这其实就是上一讲当中讲到的,对相同连接点的多个切面的先后顺序的实现了。
5.AOP代理失效原因
在有些情况下,AOP会失效,我们在AOPTestController中创建a、b两个方法,如下:
@RestController
@RequestMapping("aop")
@Api(tags = "测试AOP")
public class AOPTestController {
@Log
@PostMapping(value = "a")
public String a() {
return "a";
}
@Log
@PostMapping(value = "b")
public String b() {
return "b";
}
}
我们分别请求下a、b接口,发现的确是有日志拦截的,证明AOP是生效了的。
但是我们如果,在a方法中去调用b方法,这个时候会有b方法被调用的日志输出么?代码如下:
@Log
@PostMapping(value = "a")
public String a() {
// 手动调用b方法
b();
return "a";
}
下面是运行结果
我们发现只有a方法的日志,而没有b方法的日志,这个其实不难理解,AOP的实现原理是需要生成代理对象,当我们调用业务方法时,其实是先回调了DynamicAdvisedInterceptor中的intercept方法或者JdkDynamicAopProxy的invoke方法,然后会去遍历增强,并且会去调用业务方法,但是真正调用到业务方法时,在业务方法中去调用其他方法时,没有使用代理对象,而是直接调用的被代理对象的方法,所以就不会有拦截日志,像上面的就是直接调用的AOPTestController的b方法。这样,看起来好像AOPTestController的b方法的AOP失效了,虽然它也使用了@Log注解。
那要怎么做才能让b方法也能走日志拦截呢?
根据上面的分析,其实我们也知道答案了,就是需要通过AOPTestController的代理对象来调用b方法嘛。
Spring提供了一个AopContext类,它有一个currentProxy方法可以获取到当前类的代理对象,代码如下
@Log
@PostMapping(value = "a")
public String a() {
((AOPTestController)AopContext.currentProxy()).b();
return "a";
}
调用结果如下:
发现报错了,是需要设置exposeProxy,我们可以在启动的Application中增加如下注解:
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
这个时候,我们再调用a方法,结果如下:
可以看到,b也有拦截日志,并且是跟我们方法执行的顺序一致:a方法参数-> b方法参数->b方法返回->a方法返回