上篇文章,分析了解析<aop:config>内容并存储到BeanDefinition的过程。本篇文章,接着分析AspectJAwareAdvisorAutoProxyCreator类为Bean生成代理类的过程。
AspectJAwareAdvisorAutoProxyCreator类的继承体系
找到需要生成代理的bean
通过之前分析spring ioc过程,先进入到AbstractApplicationContext类的核心方法refresh(),找到finishBeanFactoryInitialization方法,接着进入该方法一直往下找,首先找到AbstractAutowireCapableBeanFactory类的createBean方法,方法源码:
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
// 处理方法覆盖
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
//给BeanPostProcessors一个创建代理对象的机会,如果代理对象返回不为空则createBean就直接返回了,后面的目标对象就不再实例化了。
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
// 完成Bean实例的创建(实例化、填充属性、初始化)
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
分析上述代码,resolveBeforeInstantiation方法是给BeanPostProcessors类一个机会,让它创建代理对象。接着进入resolveBeforeInstantiation方法中的applyBeanPostProcessorsBeforeInstantiation方法,方法源码:
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;
}
第5行代码,本质调用的是AbstractAutoProxyCreator类的postProcessBeforeInstantiation方法,源码如下:
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
// 1. 有些对象是不可以被代理的,基类:Advices, Advisors and AopInfrastructureBeans; 带有aop注解类: @Aspect
// 2. 子类可以复写该类,如果一些情况不需要被代理, shouldSkip返回true
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
///获取targetSource, 如果存在则直接在对象初始化之前进行创建代理, 避免了目标对象不必要的实例化
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
//如果有自定义targetSource就要这里创建代理对象
//这样做的好处是被代理的对象可以动态改变,而不是只针对一个target对象(可以对对象池中对象进行代理,可以每次创建代理都创建新对象)
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
//获取Advisors, 这个是交给子类实现的
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
//返回代理的对象
return proxy;
}
return null;
}
postProcessBeforeInstantiation中如果获取到自定义的TargetSource则直接创建代理对象,创建代理对象之前先调用getAdvicesAndAdvisorsForBean获取拦截对象Advisors,然后调用createProxy创建代理对象。
如果没有自定义TargetSource,则走到postProcessAfterInitialization方法创建代理,逻辑跟上面一样,唯一不同的是创建了个默认的TargetSource (SingletonTargetSource),方法postProcessAfterInitialization在哪呢?回头再次看AbstractAutowireCapableBeanFactory的createBean方法,找到doCreateBean方法,进入后,找到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()) {
//应用BeanPostProcessor的postProcessBeforeInitializationf方法,这里首先会对
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//执行初始化方法(先调用InitializingBean的afterPropertiesSet,再调用init-method属性指定的初始化方法)
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()) {
//应用BeanPostProcessor的postProcessAfterInitialization方法(AOP代理对象生成)
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
分析以上代码,通过注释可以知道,aop生成代理对象的核心逻辑是applyBeanPostProcessorsAfterInitialization方法。方法源码:
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
分析第6行,本质是调用BeanPostProcessor接口的子类AbstractAutoProxyCreator的postProcessAfterInitialization方法。
public Object postProcessAfterInitialization(@Nullable 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;
}
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.
// 获取advisor, 寻找Advisors,过滤,并做排序
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 通过jdk动态代理或者cglib动态代理,产生代理对象,默认用SingletonTargetSource
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;
}
分析上述代码,第15行是判断aop.xml配置文件中哪些bean需要生成代理。进入getAdvicesAndAdvisorsForBean方法,找到findEligibleAdvisors,源码如下:
//为指定class寻找合适的Advisor
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;
}
第3行代码,寻找候选Advisors,根据上文的配置文件,有两个候选Advisor,分别是aop:aspect节点下的aop:before和aop:after这两个,这两个在XML解析的时候已经被转换生成了RootBeanDefinition。
第5行extendAdvisors方法作用是向候选Advisor链的开头(也就是List.get(0)的位置)添加一个org.springframework.aop.support.DefaultPointcutAdvisor。
第4行代码,根据候选Advisors,寻找可以使用的Advisor,依次进入findAdvisorsThatCanApply->findAdvisorsThatCanApply,方法findAdvisorsThatCanApply源码如下:
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> 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;
}
重点看下canApply方法,进入:
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
方法的第一个参数advisor的实际类型是AspectJPointcutAdvisor,它是PointcutAdvisor的子类,因此执行第7行的方法:
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();
if (methodMatcher == MethodMatcher.TRUE) {
// No need to iterate the methods if we're matching any method anyway...
return true;
}
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set<Class<?>> classes = new LinkedHashSet<>();
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
此方法对Advisor对应的expression进行两次判断:
- 目标类必须满足expression的匹配规则
- 目标类中的方法必须有一个满足expression的匹配规则
如果bean满足这个两个条件,那么容器会对该bean生成代理对象.具体方式为返回一个数组对象,该数组对象中存储的是<bean>对应的Advisor。
spring为<bean>生成代理
回来看AbstractAutoProxyCreator的wrapIfNecessary方法,第15行拿到<bean>对应的Advisor数组,若不为空,则就会通过调用createProxy方法为<bean>创建代理,方法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);
//判断的内容是<aop:config>这个节点中proxy-target-class="false"或者proxy-target-class不配置,即不使用CGLIB生成代理
//如果满足条件,进入evaluateProxyInterfaces方法,获取当前Bean实现的所有接口,把这些接口Class对象都添加到ProxyFactory中
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 把指定和通用拦截对象合并, 并都适配成Advisor
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 获取使用JDK动态代理或者cglib动态代理产生的对象
return proxyFactory.getProxy(getProxyClassLoader());
}
进入proxyFactory.getProxy方法:
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
此getProxy方法,是用AopProxyFactory代理工厂创建AopProxy, 然后用AopProxy创建Proxy代理对象。这里的AopProxyFactory默认是DefaultAopProxyFactory,看它的createAopProxy方法:
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);
}
}
平时我们说AOP原理三句话就能概括:
1、对类生成代理使用CGLIB
2、对接口生成代理使用JDK原生的Proxy
3、可以通过配置文件指定对接口使用CGLIB生成代理
这三句话的出处就是createAopProxy方法。看到默认是第14行的代码使用JDK自带的Proxy生成代理,以下三种情况例外:
1、ProxyConfig的isOptimize方法为true,这表示让Spring自己去优化而不是用户指定
2、ProxyConfig的isProxyTargetClass方法为true,这表示配置了proxy-target-class=“true”
3、ProxyConfig满足hasNoUserSuppliedProxyInterfaces方法执行结果为true,这表示<bean>对象没有实现任何接口或者实现的接口是SpringProxy接口
在进入第2行的if判断之后再根据目标<bean>的类型决定返回哪种AopProxy。
总结:
1、proxy-target-class没有配置或者proxy-target-class=“false”,返回JdkDynamicAopProxy
2、proxy-target-class="true"或者对象没有实现任何接口或者只实现了SpringProxy接口,返回Cglib2AopProxy
不管是JdkDynamicAopProxy还是Cglib2AopProxy,AdvisedSupport都是作为构造函数参数传入的,里面存储了具体的Advisor。
通过getProxy方法获取<bean>对应的代理
根据上述分析,查看下JdkDynamicAopProxy生成代理的方式:
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
第5行代码的作用是拿到所有要代理的接口,第6行代码的作用是尝试寻找这些接口方法里面有没有equals方法和hashCode方法,同时都有的话打个标记,寻找结束,equals方法和hashCode方法有特殊处理。
最终通过第7行的Proxy.newProxyInstance方法获取接口/类对应的代理对象,Proxy是JDK原生支持的生成代理的方式。
jdk动态代理的调用原理
链接:https://www.cnblogs.com/xrq730/p/6757608.html
上述分析,最后生成了代理对象,生成代理之后就要调用方法了,由于JdkDynamicAopProxy本身实现了InvocationHandler接口,因此具体代理前后处理的逻辑在JdkDynamicAopProxy类的invoke方法中:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else 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;
}
// Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 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.
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();
}
// 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())) {
// 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);
}
}
}
第10行~第17行的代码,表示equals方法与hashCode方法即使满足expression规则,也不会为之产生代理内容,调用的是JdkDynamicAopProxy的equals方法与hashCode方法。
第22行~第26行的代码,表示方法所属的Class是一个接口并且方法所属的Class是AdvisedSupport的父类或者父接口,直接通过反射调用该方法。
第30行~第34行的代码,是用于判断是否将代理暴露出去的,由aop:config标签中的expose-proxy="true/false"配置。
第42行的代码,获取AdvisedSupport中的所有拦截器和动态拦截器列表,用于拦截方法,具体到我们的实际代码,列表中有三个Object,分别是:
chain.get(0):ExposeInvocationInterceptor,这是一个默认的拦截器,对应的原Advisor为DefaultPointcutAdvisor
chain.get(1):MethodBeforeAdviceInterceptor,用于在实际方法调用之前的拦截,对应的原Advisor为AspectJMethodBeforeAdvice
chain.get(2):AspectJAfterAdvice,用于在实际方法调用之后的处理
第46行~第52行的代码,如果拦截器列表为空,很正常,因为某个类/接口下的某个方法可能不满足expression的匹配规则,因此此时通过反射直接调用该方法。
第53行~第58行的代码,如果拦截器列表不为空,按照注释的意思,需要一个ReflectiveMethodInvocation,并通过proceed方法对原方法进行拦截,proceed方法里面使用到了递归的思想,对chain中的Object进行循环调用。