本文共 23940 字,大约阅读时间需要 79 分钟。
上一篇我们讲解了Spring对aop配置的处理,但是还没有讲Spring中是怎么运用这些配置的。今天我们就俩看下Spring是怎么让这些东西起作用的。
在讲解之前,我们需要先认识一下BeanPostProcessor接口。
我们回到AbstractApplicationContext的refresh方法。
@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); // Initialize message source for this context. initMessageSource(); // Initialize event multicaster for this context. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // Check for listener beans and register them. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); } catch (BeansException ex) { logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex); // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } } }
我们解析aop配置的操作是在 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();中完成的。
我们继续往下看,可以看到有registerBeanPostProcessors(beanFactory);方法
这个方法就是把所有的实现BeanPostProcessor接口的Bean都注入到AbstractBeanFactory的beanPostProcessors属性中。这个跟invokeBeanFactoryPostProcessors方法中将所有实现了BeanFactoryPostProcessor接口的Bean都注入到相应的list集合中并调用其postProcessBeanFactory方法的实现是大体一样的,这里就不再说了,可以看看之前讲解Spring解析属性文件的源码解析部分。
然后我们就直接看到实例化bean的代码段把,在refresh就是 finishBeanFactoryInitialization(beanFactory);的具体实现,我们不一层一层看了,直接看AbstractAutowireCapableBeanFactory类的
initializeBean
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction
这个方法我们已经不陌生了,我们在讲解SpringMVC的时候提到过InitializingBean接口,如果Bean实现了这个接口,会在实例化Bean的时候通过该方法中的invokeInitMethods来调用afterPropertiesSet()方法。而今天在我们关注的BeanPostProcessor接口中,在这个类对应的方法很显然就是
applyBeanPostProcessorsBeforeInitialization和applyBeanPostProcessorsAfterInitialization方法。
@Override public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { result = beanProcessor.postProcessBeforeInitialization(result, beanName); if (result == null) { return result; } } return result; }
一目了然,就是遍历所有的BeanPostProcessor实现类(已经在registerBeanPostProcessors得到了所有的实现类集合),然后以当前Bean的信息为参数来调用他的postProcessBeforeInitialization方法。
同理如果是applyBeanPostProcessorsAfterInitialization方法,便是遍历后调用postProcessAfterInitialization方法。
分析到这里,很明显我们就可以吧目光转向AspectJAwareAdvisorAutoProxyCreator的这两个方法了。
在我们上一篇讲解ConfigBeanDefinitionParser的parse方法的时候,说到 configureAutoProxyCreator(parserContext, element);的时候说先不细说,那么到了这一篇就需要从这里入手了。
private void configureAutoProxyCreator(ParserContext parserContext, Element element) { AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element); } public static void registerAspectJAutoProxyCreatorIfNecessary( ParserContext parserContext, Element sourceElement) { BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary( parserContext.getRegistry(), parserContext.extractSource(sourceElement)); useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement); registerComponentIfNecessary(beanDefinition, parserContext); }
1.得到一个包含AspectJAwareAdvisorAutoProxyCreator实例的Bean定义。
2.根据element节点的相关属性设置一些属性。
3.将1中得到的Bean定义注册到Spring容器中。
我们详细说一下1和2.
registerAspectJAutoProxyCreatorIfNecessary
public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) { return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source); } private static BeanDefinition registerOrEscalateApcAsRequired(Class cls, BeanDefinitionRegistry registry, Object source) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); if (!cls.getName().equals(apcDefinition.getBeanClassName())) { int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName()); int requiredPriority = findPriorityForClass(cls); if (currentPriority < requiredPriority) { apcDefinition.setBeanClassName(cls.getName()); } } return null; } RootBeanDefinition beanDefinition = new RootBeanDefinition(cls); beanDefinition.setSource(source); beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE); beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition); return beanDefinition; }
1)当Spring容器中已经有名为org.springframework.aop.config.internalAutoProxyCreator的Bean。
获取对应的Bean定义,把这个Bean定义的ClassName和AspectJAwareAdvisorAutoProxyCreator比较,如果不相同,比较两个ClassName的优先级。如果AspectJAwareAdvisorAutoProxyCreator的优先级高,则把当前的Bean定义的ClassName设置为AspectJAwareAdvisorAutoProxyCreator。优先级为:
AnnotationAwareAspectJAutoProxyCreator>AspectJAwareAdvisorAutoProxyCreator>InfrastructureAdvisorAutoProxyCreator。
2)如果当前容器中并没有这个BeanName存在。那么就使用AspectJAwareAdvisorAutoProxyCreator构造出一个Bean定义,并注册一些相关属性,把order优先级设置为最低等等。然后返回。
useClassProxyingIfNecessary
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, Element sourceElement) { if (sourceElement != null) { boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE)); if (proxyTargetClass) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); } boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE)); if (exposeProxy) { AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry); } } }
是不是看到了熟悉的东西,proxy-target-class属性在我们一开始学习aop配置的时候经常会提到,人们通常会告诉你,如果你想对类直接使用动态,那可以在\节点里配置属性:proxy-target-class=true即可,那么动态代理就会使用cglib来完成,cglib可以直接针对类来实现动态代理,而如果我们在aop配置的时候没有设置这个属性或者设置为false,那么就会使用JDK动态代理,这个时候就只能针对接口实现动态代理。
那么这个方法其实他的主要作用就是为了上述的Bean定义注册两个属性,分别是proxyTargetClass和exposeProxy。
好了到现在,我们终于往Spring容器中注入了AspectJAwareAdvisorAutoProxyCreator构成的Bean定义。
我们来看下AspectJAwareAdvisorAutoProxyCreator的继承结构。
public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator { public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator { public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware { public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor { public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor { public class ProxyProcessorSupport extends ProxyConfig implements Ordered, BeanClassLoaderAware, AopInfrastructureBean {
我们发现他的祖先类有实现了BeanPostProcessor接口。
翻阅源码,你会发现AspectJAwareAdvisorAutoProxyCreator以及他的祖先类都没有对postProcessBeforeInitialization方法有具体的实现,而只有对postProcessAfterInitialization方法有具体实现。
这个方法的实现在祖先类AbstractAutoProxyCreator中。
@Override 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; }
我们看方法的重点wrapIfNecessary
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (beanName != null && 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; }
1.通过getAdvicesAndAdvisorsForBean来获取可以对当前Bean做代理的AdviceBean。
2.如果AdviceBean不为空,则创建动态代理类,最后把其放入缓存,然后返回。
getAdvicesAndAdvisorsForBean
AbstractAdvisorAutoProxyCreator
@Override protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName, TargetSource targetSource) { Listadvisors = findEligibleAdvisors(beanClass, beanName); if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray(); }
利用当前bean的Class和beanName来找到匹配的Advisors
protected ListfindEligibleAdvisors(Class beanClass, String beanName) { List candidateAdvisors = findCandidateAdvisors(); List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }
1)先获取所有的Advisor
2)然后调用findAdvisorsThatCanApply在所有的Advisor找到符合条件的Advisor集合。
protected ListfindAdvisorsThatCanApply( List candidateAdvisors, Class beanClass, String beanName) { ProxyCreationContext.setCurrentProxiedBeanName(beanName); try { return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass); } finally { ProxyCreationContext.setCurrentProxiedBeanName(null); } } public static List findAdvisorsThatCanApply(List candidateAdvisors, Class clazz) { if (candidateAdvisors.isEmpty()) { return candidateAdvisors; } List eligibleAdvisors = new LinkedList (); for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) { eligibleAdvisors.add(candidate); } } boolean hasIntroductions = !eligibleAdvisors.isEmpty(); for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor) { // already processed continue; } if (canApply(candidate, clazz, hasIntroductions)) { eligibleAdvisors.add(candidate); } } return eligibleAdvisors; }
我们可以看到选出适合的Advisor的主要方法是canApply,我们主要看这个方法。
canApply
public static boolean canApply(Pointcut pc, Class targetClass, boolean hasIntroductions) { Assert.notNull(pc, "Pointcut must not be null"); if (!pc.getClassFilter().matches(targetClass)) { return false; } MethodMatcher methodMatcher = pc.getMethodMatcher(); IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null; if (methodMatcher instanceof IntroductionAwareMethodMatcher) { introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher; } Set> classes = new LinkedHashSet >(ClassUtils.getAllInterfacesForClassAsSet(targetClass)); classes.add(targetClass); for (Class clazz : classes) { Method[] methods = clazz.getMethods(); for (Method method : methods) { if ((introductionAwareMethodMatcher != null && introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) || methodMatcher.matches(method, targetClass)) { return true; } } } return false; }
接下来看创建代理对象
createProxy
protected Object createProxy( Class beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) { 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); for (Advisor advisor : advisors) { proxyFactory.addAdvisor(advisor); } proxyFactory.setTargetSource(targetSource); customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } return proxyFactory.getProxy(getProxyClassLoader()); }
这个方法大体的意思就是新建一个ProxyFactory对象,然后将满足条件的Advisor信息都注入到这个对象中,最后调用 proxyFactory.getProxy(getProxyClassLoader());来创建代理对象。
getProxy
public Object getProxy(ClassLoader classLoader) { return createAopProxy().getProxy(classLoader); }
createAopProxy
protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } return getAopProxyFactory().createAopProxy(this); }
最终调用的是DefaultAopProxyFactory的createAopProxy方法
@Override 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()) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } }
方法很容易理解,如果proxy-target-class属性指定为true,而且不是对接口进行动态代理,就调用ObjenesisCglibAopProxy来完成动态代理,即使用CGLIB来完成动态代理。否则就是调用JdkDynamicAopProxy来完成动态代理,即使用JDK动态代理来实现。
我们先看我们熟悉的JDK动态代理的具体实现。
JdkDynamicAopProxy
@Override public Object getProxy(ClassLoader classLoader) { if (logger.isDebugEnabled()) { logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource()); } Class [] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); }
getProxy的方法很简单,就是使用当前的ClassLoader来加载当前Bean实现的所有接口,最后生成相应的动态代理实例。
至此,创建动态代理实例的过程就分析完了。
但是更重要的是当我们调用动态代理实例时,JdkDynamicAopProxy中对InvocationHandler接口的的具体实现。
invoke
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { MethodInvocation invocation; Object oldProxy = null; boolean setProxyContext = false; TargetSource targetSource = this.advised.targetSource; Class targetClass = null; Object target = null; try { if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { // The target does not implement the equals(Object) method itself. return equals(args[0]); } if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. return hashCode(); } if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { // Service invocations on ProxyConfig with the proxy config... return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } Object retVal; 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 = targetSource.getTarget(); if (target != null) { targetClass = target.getClass(); } // Get the interception chain for this method. List
我们直接看重点,直接跳过对不需要执行增强方法的方法的处理。
调用this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);来获得当前方法匹配的Advisor集合。
当Advisor集合不为空的时候,执行
// 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();
这两行就是关键。
我们重点看ReflectiveMethodInvocation的proceed()方法
@Override public Object proceed() throws Throwable { // We start with an index of -1 and increment early. if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); } Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { // Evaluate dynamic method matcher here: static part will already have // been evaluated and found to match. InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) { return dm.interceptor.invoke(this); } else { // Dynamic matching failed. // Skip this interceptor and invoke the next in the chain. return proceed(); } } else { // It's an interceptor, so we just invoke it: The pointcut will have // been evaluated statically before this object was constructed. return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }
这里的主要操作就是使用责任链模式来调用chain集合里的interceptor属性的invoke方法。
所以我们只要来看看这个chain到底是怎么个东西就好了。具体怎么得到这个chain的我们就不细说了,有兴趣的可以看源码(DefaultAdvisorAdapterRegistry的getInterceptors方法),chain集合是一个MethodInterceptor集合。
这个Intercepor集合主要包含下面几种:
AspectJAfterThrowingAdvice 对应着aop配置里面\节点里的方法。
AspectJAfterAdvice 对应着 \
AspectJAroundAdvice 对应着 \
AfterReturningAdviceInterceptor 对应着AfterReturningAdvice 对应着 \
MethodBeforeAdviceInterceptor 对应着 MethodBeforeAdvice 对应着\
这几种MethodInterceptor调用的先后顺序,如果没有在配置文件中指定Order,那么就会以在配置文件中出现的顺序来执行。执行的过程是一个责任链模式的应用,有兴趣的同学可以先一个例子debug深入研究。
转载地址:http://jdmvb.baihongyu.com/