前言
上一篇我们讲解了Spring对aop配置的处理,但是还没有讲Spring中是怎么运用这些配置的。今天我们就俩看下Spring是怎么让这些东西起作用的。
BeanPostProcessor
在讲解之前,我们需要先认识一下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<Object>() {
@Override
public Object run() {
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;
}
这个方法我们已经不陌生了,我们在讲解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的这两个方法了。
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) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
利用当前bean的Class和beanName来找到匹配的Advisors
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;
}
1)先获取所有的Advisor
2)然后调用findAdvisorsThatCanApply在所有的Advisor找到符合条件的Advisor集合。
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
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<Class<?>> classes = new LinkedHashSet<Class<?>>(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<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
if (chain.isEmpty()) {
// 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.
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
}
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();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
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()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
我们直接看重点,直接跳过对不需要执行增强方法的方法的处理。
调用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深入研究。