spring5.0源碼解析 Aop 02
- 建立 AopProxy對象
-
- 設計原理
-
- ProxyConfig
- AdvisedSupport
- ProxyFactoryBean
- getObject傳回此工廠Aop代理執行個體
- proxyFactory
- AspectProxyFactory、 proxyFactory 、 ProxyFactoryBean 的差別
-
-
-
- initializeAdvisorChain 初始化通知鍊
- getSingletonInstance 生成單例的代理對象
- AopProxy
-
-
建立 AopProxy對象
設計原理
在spring 的 Aop子產品中,是通過配置和調用Spring的ProxyFactoryBean來完成這個任務的,在 ProxyFactoryBean 中,封裝了主要代理對象的生成過程,這個過程由JDK的Proxy和CGLibL兩種方式實作
在這個 類繼承關系中,可以看到完成 AOP應用的類,比如AspectJProxyFactory、TransactionProxyFactoryBean , 具體的對象的生成分别由 ProxyFactoryBean,AspectJProxyFactory和ProxyFactory來完成,**ProxyFactoryBean和ProxyFactory都提供了AOP功能的封裝,隻是使用ProxyFactoryBean可以在Ioc容器中完成聲明式配置,而是用ProxyFactory 則需要程式設計式使用Aop的功能
ProxyConfig
用于建立代理的配置的友善超類,以確定所有代理建立者具有一緻的屬性
// 是否直接代理目标類,為不是代理特定的接口
private boolean proxyTargetClass = false;
// 标記是否對代理進行優化。啟動優化通常意味着在代理對象被建立後,增強的修改将不會生效,是以預設值為false。
private boolean optimize = false;
//該屬性用于空值生成的代理對象是否可以強制轉型為Advised,預設值為false,表示任何生成的代理對象都可以強制轉換成Advised,true是不可以,可以通過Adviced查詢代理對象的一些狀态
boolean opaque = false;
// 标記代理對象是否應該被aop架構通過AopContext以ThreadLocal的形式暴露出去。
// 當一個代理對象需要調用它自己的另外一個代理方法時,這個屬性将非常有用。預設是是false,以避免不必要的攔截。
boolean exposeProxy = false;
// 标記該配置是否需要被當機,如果被當機,将不可以修改增強的配置。
// 如果該值為true,那麼代理對象的生成的各項資訊配置完成,則不容許更改,如果ProxyFactory設定完畢,該值為true,則不能對Advice進行改動,可以優化代理對象生成的性能。預設情況下該值為false
private boolean frozen = false;
AdvisedSupport
可以将他看成其子類建立Aop代理對象的一個輔助類。
配置目前代理的Adivsiors
配置目前代理的目标對象
配置目前代理的接口
提供getInterceptorsAndDynamicInterceptionAdvice方法用來擷取對應代理方法對應有效的攔截器鍊
ProxyFactoryBean
getObject傳回此工廠Aop代理執行個體
ProxyFactoryBean 實作了 FactoryBean getObject傳回此工廠Aop代理執行個體
// 建立此工廠傳回的AOP代理執行個體。
@Override
@Nullable
public Object getObject() throws BeansException {
// 初始化通知器鍊
initializeAdvisorChain();
// 這裡對singleton和prititype類型進行了區分,生成對象的proxy
if (isSingleton()) {
return getSingletonInstance();
}
else {
if (this.targetName == null) {
logger.info("Using non-singleton proxies with singleton targets is often undesirable. " +
"Enable prototype proxies by setting the 'targetName' property.");
}
return newPrototypeInstance();
}
}
proxyFactory
在專欄前面的文章介紹了 使用ProxyFactoryBean 實作擷取Aop代理對象。 ProxyFactoryBean 與 proxyFactory 的實作原理是一樣的 ,不過是對 攔截器、切入點進行整合,通過遞歸的形式生成代理對象的過程,隻是他們兩個在最外層的表現上有所不同。
proxyFactory 是 ProxyCreatorSupport 的子類,proxyFactory 擷取代理對象也是通過 getProxy方法為入口,由 getAopProxyFactory 完成 , 而 ProxyCreatorSupport 也繼承了 AdvisedSupport 具有了 通知和切入點的支援
public <T> T getProxy() {
return (T) createAopProxy().getProxy();
}
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
// getAopProxyFactory 擷取的是 DefaultAopProxyFactory 對象
return getAopProxyFactory().createAopProxy(this);
}
AspectProxyFactory、 proxyFactory 、 ProxyFactoryBean 的差別
- proxyFactory 這種是寫死的方式,可以脫離spring直接使用。
- AspectProxyFactory 實作了 @AspectJ 注解的形式 我們隻需要配置切面、通知、切點表達式就能自動的實作切入的效果
- ProxyFactoryBean 是建立AOP的最基本的方式。是将我們的AOP和IOC融合起來,而ProxyFactory 則是隻能通過代碼寫死進行編寫 一般都是給spring自己使用。
initializeAdvisorChain 初始化通知鍊
// 初始化通知鍊
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
// 判斷是否初始化過 , 通知鍊隻出初始化一次
if (this.advisorChainInitialized) {
return;
}
if (!ObjectUtils.isEmpty(this.interceptorNames)) {
if (this.beanFactory == null) {
throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
"- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
}
// Globals can't be last unless we specified a targetSource using the property...
if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&
this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
throw new AopConfigException("Target required after globals");
}
// Materialize interceptor chain from bean names.
// 從bean名稱具體化攔截器鍊。
for (String name : this.interceptorNames) {
// 如果攔截器name 以 * 号結尾
if (name.endsWith(GLOBAL_SUFFIX)) {
if (!(this.beanFactory instanceof ListableBeanFactory)) {
throw new AopConfigException(
"Can only use global advisors or interceptors with a ListableBeanFactory");
}
addGlobalAdvisors((ListableBeanFactory) this.beanFactory,
name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
}
else {
// If we get here, we need to add a named interceptor.
// We must check if it's a singleton or prototype.
//需要添加一個命名攔截器。必須檢查它是單體還是原型。
Object advice;
if (this.singleton || this.beanFactory.isSingleton(name)) {
// Add the real Advisor/Advice to the chain.
advice = this.beanFactory.getBean(name);
}
else {
// It's a prototype Advice or Advisor: replace with a prototype.
// Avoid unnecessary creation of prototype bean just for advisor chain initialization.
advice = new PrototypePlaceholderAdvisor(name);
}
//将給定的advice, advisor或對象添加到攔截器清單中。
addAdvisorOnChainCreation(advice);
}
}
}
this.advisorChainInitialized = true;
}
getSingletonInstance 生成單例的代理對象
getSingletonInstance 這個方法是 proxyFactoryBean生成AopProxy代理對象的調用接口。代理對象會封裝對target目标對象的調用,也就是說針對target對象的調用行為會被這裡生成的代理對象所攔截,
// 傳回這個類的代理對象的單例執行個體,如果尚未建立,則延遲建立。
private synchronized Object getSingletonInstance() {
if (this.singletonInstance == null) {
// 被代理的目标對象
this.targetSource = freshTargetSource();
if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
// Rely on AOP infrastructure to tell us what interfaces to proxy.
// 依靠AOP基礎設施告訴我們代理的接口。
Class<?> targetClass = getTargetClass();
if (targetClass == null) {
throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
}
// 設定代理對象的接口
setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
}
// 初始化共享單例執行個體。
super.setFrozen(this.freezeProxy);
// 生成具體的代理對象
this.singletonInstance = getProxy(createAopProxy());
}
return this.singletonInstance;
}
// 擷取代理對象
protected Object getProxy(AopProxy aopProxy) {
return aopProxy.getProxy(this.proxyClassLoader);
}
AopProxy
spring 利用 AopProxy 接口類把Aop代理對象的實作與架構其他部分有效的分開,他有兩個子類 CglibAopProxy 和 JdkDynamicAopProxy 分别采用 CGLIB和 JDK來生成代理對象。
生成 AopProxy 是通過 AopProxyFactory來實作的,至于生成什麼樣的代理對象封裝在 AdvisedSupport 中,也是 ProxyFactoryBean 的父類
// 通過 AopProxyFactory 生成 AopProxy
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
DefaultAopProxyFactory.createAopProxy 方法 根據 AdvisedSupport 生成AopProxy 這裡決定了使用CGLIB還是Jdk的的方式
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!NativeDetector.inNativeImage() &&
(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.");
}
// 如果targetClass是接口類,使用Jdk 來生成
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 使用Cglib 生成
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
在AopProxy代理對象生成過程中,首先要從AdvisedSupport對象中取得配置的目标對象,在完成目标對象的檢查後,根據配置情況來決定使用什麼方式來建立AopProxy代理對象。