Spring AOP Java Dynamic Proxy CGLIB

Spring AOP - Java Dynamic Proxy and CGLib

胡育群 2016/12/15 20:04:34
1790







主題

Spring AOP - Java Dynamic Proxy and CGLib

文章簡介

Spring會依照不同設定實作AOP,本文介紹其中的兩種實作機制Java Dynamic ProxyCGLib Proxy及其限制。

作者

胡育群

版本/產出日期

V1.0/2016.12.12




1. 前言

AOP(Aspect-Oriented Programming)可將散落在各個商務流程中的共同邏輯集結成獨立可重用的服務,且不會與應用程式發生耦合,隨時可抽換。

Spring在AOP上的應用很多,會依據設定使用不同機制實現。目前支援三種機制:Java Dynamic Proxy、CGLib Proxy、AspectJ,本文利用簡單的應用介紹前面兩種Proxy機制。





2. 目的

了解Spring在不同設定下對AOP的實作機制及其限制,利於專案初期規劃,避免日後重構。






3. 開始前準備

本架構建立於以下版本的環境:

JDK8

STS 3.6.2.RELEASE

Maven3.2.1(STS 3.6.2中內建)











4. Java Dynamic Proxy

4.1、 物件關聯

1Java Dynamic Proxy Class diagram

Proxy(java.lang.reflect.Proxy)在執行期創建實作DemoService介面的$Proxy物件。

$Proxy物件關聯至InvocationHandlerImpl,進行攔截。

InvocationHandlerImpl需擁有被代理的DemoServiceImpl1物件,才能呼叫到需執行的功能。


4.2、 作業流程

2Java Dynamic Proxy Control flow

所有被$Proxy實作到的功能,呼叫時會先被dispatch到關聯的InvocationHandlerImpl中的invoke。

invoke執行加入的服務模組,再呼叫被代理的DemoServiceImpl1物件中原有功能。





4.3、 依照 1實現Demo程式

3DemoService 被代理的物件實作的介面


4DemoServiceImpl1 被代理的物件


5JavaDynamicProxySample1 流程Demo


6Console log JavaDynamicProxySample1 Run on Java Application


4.4、 歸納出Java Dynamic Proxy有以下幾點限制

無法攔截static method。

無法攔截未定義在介面上的method,換言之只能攔截public method。

無法攔截內部呼叫method。


5. CGLib Proxy

5.1、 物件關聯

7CGLib Proxy Class diagram

CGLib Proxy Enhancer(org.springframework.cglib.proxy.Enhancer)在執行期創建繼承DemoServiceImpl2的DemoServiceImpl2$$EnhancerByCGLIB$$物件。

DemoServiceImpl2$$EnhancerByCGLIB$$物件關聯至MethodInterceptorImpl,進行攔截。


5.2、 作業流程

8CGLib Proxy Control flow


5.3、 依照 7實現Demo程式

9DemoServiceImpl2 被代理的物件

10CGLibProxySample1 流程Demo


11Console log CGLibProxySample2 Run on Java Application


5.4、 歸納出CGLib Proxy有以下幾點限制

無法攔截static method。

無法攔截無法繼承的method。

無法攔截內部呼叫method。






6. Spring AOP設定

6.1、 Spring要用哪一種AOP實作機制決定要素

若被攔截的bean有繼承介面,使用Java Dynamic Proxy,反之被攔截bean未繼承任何介面,則會使用CGLib Proxy。

Java config可以在bean上加@Scope,強制使用何種Proxy,如圖 9,DemoServiceImpl2雖然有繼承DemoService介面,但是使用CGLib Proxy實作。

Xml config 可以加上scoped-proxy或proxy-target-class屬性來決定使用何種方式實作。


6.2、 Demo程式

12pom.xml maven設定



13PointcutDefinition Pointcut定義



14LoggerAspect 定義需要動態加入的服務

15SpringAopSample1Application Demo Spring AOP use Spring Boot

DemoService參考圖 3。

DemoServiceImpl1參考圖 4。

DemoServiceImpl2參考圖 9。


16Console log SpringAopSample1Application Run on Java Application


7. Proxy機制限制及解決方法

7.1、 Proxy機制限制

Proxy機制是在執行期間創建一個Proxy類別所以有以下限制

無法攔截不能繼承的method

Java Dynamic Proxy為介面繼承,只能繼承public method。

CGLib為類別繼承,不能繼承private or static method。


無法攔截內部呼叫method(沒有經過Proxy類別)。

7.2、 解決辦法

使用AspectJ進行程式碼的織入,支援compile time、load time weaving。


8. 參考來源

AOP概念-

http://openhome.cc/Gossip/SpringGossip/AOPConcept.html

Java Dynamic Proxy-

https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/proxy.html

CGLib Proxy -

https://github.com/cglib/cglib

Spring AOP-http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html

Spring proxy pitfalls -

http://www.nurkiewicz.com/2011/10/spring-pitfalls-proxying.html

胡育群