Spring AOP初始化的起點是在bean初始化流程后置處理中。
/**
* bean的初始化流程
*/
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 {
// 為bean包裝相關屬性,如名稱、類加載器、所屬容器等
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 調用BeanPostProcessor的postProcessBeforeInitialization前置處理方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 執行bean初始化方法
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后置處理方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
applyBeanPostProcessorsAfterInitialization方法調用了BeanPostProcessor的postProcessAfterInitialization后置處理方法
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
// 為Bean添加所有BeanPostProcessor的后置處理器
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
BeanPostProcessor的bean初始化前置處理和初始化后置處理方法均委派其子類實現,其實現子類有很多,其中創建AOP代理對象的子類是AbstractAutoProxyCreator,它實現了postProcessAfterInitialization方法。
下面具體可以分析一下AbstractAutoProxyCreator類的postProcessAfterInitialization方法。
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
if (bean != null) {
// 根據給定的bean的class和name構建一個key
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// 如果它適合被代理,則需要封裝指定的bean
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;
}
// 判斷是否是基礎設施類,或者是否配置了無需自動代理。如果是,緩存key並直接返回
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;
}
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
......
return proxyFactory.getProxy(getProxyClassLoader());
}
通過上圖可以看到,創建代理對象Spring提供了兩種方式,JDK動態代理和Cglib AOP代理。
進入createAopProxy()方法,發現這個方法最終在DefaultAopProxyFactory類中被實現。
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// isOptimize:用來控制通過CGLIB創建的代理是否使用激進的優化策略
// isProxyTargetClass:為true時,目標類本身被代理而不是目標類的接口,即使用CGLIB創建代理
// hasNoUserSuppliedProxyInterfaces:是否存在代理接口
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.");
}
// 如果是接口或是一個代理對象就要jdk動態代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
如果目標對象實現了接口,默認情況下會采用JDK動態代理,但也可以通過配置(proxy-target-class=true)強制使用CGLIB。
如果目標對象沒有實現接口,必須采用CGLIB庫。
JdkDynamicAopProxy類實現了InvocationHandler接口,我們知道InvocationHandler是JDK動態代理的核心,生成的代理對象的方法調用都會委派到invoke()方法中。
JdkDynamicAopProxy的invoke()方法的核心邏輯為:
先獲取應用到目標方法上的攔截器鏈(Interceptor Chain),如果有攔截器則應用攔截器(before、after、afterReturning等),並執行連接點(JoinPoint)。如果沒有攔截器,則直接反射執行連接點。
JDK動態代理與CGLIB的區別:
JDK動態代理只能對實現了接口的類生成代理,不能針對類。
CGLIB是針對類實現代理,主要是對指定的類生成一個子類,覆蓋其中的方法,所以該類和方法要保證可以被繼承與覆蓋。
————————————————
版權聲明:本文為CSDN博主「KeepMoving++」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/u011212394/java/article/details/101795460