標籤:java jdk 反射機制 動態代理 cglib
JAVA反射機制
JAVA反射機制在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態擷取的資訊以及動態調用對象的方法的功能稱為java語言的反射機制。JAVA反射(放射)機制:“程式運行時,允許改變程式結構或變數類型,這種語言稱為動態語言”。從這個觀點看,Perl,Python,Ruby是動態語言,C++,Java,C#不是動態語言。但是JAVA有著一個非常突出的動態相關機制:Reflection,用在Java身上指的是我們可以於運行時載入、探知、使用編譯期間完全未知的classes。換句話說,Java程式可以載入一個運行時才得知名稱的class,獲悉其完整構造(但不包括methods定義),並產生其對象實體、或對其fields設值、或喚起其methods。
JAVA的動態代理
代理模式
代理模式是常用的java設計模式,他的特徵是代理類與委託類有同樣的介面,代理類主要負責為委託類預先處理訊息、過濾訊息、把訊息轉寄給委託類,以及事後處理訊息等。代理類與委託類之間通常會存在關聯關係,一個代理類的對象與一個委託類的對象關聯,代理類的對象本身並不真正實現服務,而是通過調用委託類的對象的相關方法,來提供特定的服務。
按照代理的建立時期,代理類可以分為兩種。
靜態代理:由程式員建立或特定工具自動產生原始碼,再對其編譯。在程式運行前,代理類的.class檔案就已經存在了。
動態代理:在程式運行時,運用反射機制動態建立而成。
JDK的動態代理機制只能代理實現了介面的類,而不能實現介面的類就不能實現JDK的動態代理,cglib是針對類來實現代理的,他的原理是對指定的目標類產生一個子類,並覆蓋其中方法實現增強,但因為採用的是繼承,所以不能對final修飾的類進行代理。
pom.xml引入相關jar
<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.1</version></dependency>
代碼
package com.eyugame.test.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;/** * jdk內建動態代理 * @author JYC506 * */public class JDKProxy implements InvocationHandler {private Object target;/** * 綁定委派物件並返回一個代理類 * * @param T * 要代理的類 * @return * @throws IllegalAccessException * @throws InstantiationException */@SuppressWarnings("unchecked")public <superClazz> superClazz getInstance(Class<?> T,Class<?> superClazz) throws InstantiationException, IllegalAccessException {this.target = T.newInstance();// 取得代理對象return (superClazz) Proxy.newProxyInstance(T.getClassLoader(), T.getInterfaces(), this); // 要綁定介面(這是一個缺陷,cglib彌補了這一缺陷)}/** * 綁定委派物件並返回一個代理類 * * @param T * 要代理的類 * @return * @throws IllegalAccessException * @throws InstantiationException */@SuppressWarnings("unchecked")public <superClazz> superClazz getInstance(Object target ,Class<?> superClazz) {this.target =target;Class<?> clazz=this.target.getClass();// 取得代理對象return (superClazz) Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(), this); // 要綁定介面(這是一個缺陷,cglib彌補了這一缺陷)}/** * */public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object result = null;System.out.println("事物開始");result = method.invoke(target, args);System.out.println("事物結束");return result;}public static void main(String[] args) {JDKProxy proxy = new JDKProxy();Idog dog1 = null;Idog dog2=new Dog();try {dog1 = proxy.getInstance(Dog.class,Idog.class);dog2=proxy.getInstance(new Dog(),Idog.class);dog1.doSomething();dog2.setId(23);System.out.println(dog2.getId());} catch (Exception e) {e.printStackTrace();}}}class Dog implements Idog { private int id; public void doSomething() {System.out.println("call doSomething()");}@Overridepublic void setId(int id) {this.id=id;}@Overridepublic int getId() {return this.id;}}interface Idog {void doSomething();void setId(int id);int getId();}運行結果
package com.eyugame.test.proxy;import java.lang.reflect.Method;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;/** * cglib動態代理 * @author JYC506 * */public class CglibProxy implements MethodInterceptor {/** * 建立代理對象 * * @param target * @return */@SuppressWarnings("unchecked")public <T> T getInstance(Class<?> T) {Enhancer enhancer = new Enhancer();/* 指定父類 */enhancer.setSuperclass(T);// 回調方法enhancer.setCallback(this);// 建立代理對象return (T)enhancer.create();}@Override// 回調方法public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("事物開始");Object o = proxy.invokeSuper(obj, args);System.out.println("事物結束");return o;}public static void main(String[] args) {CglibProxy proxy = new CglibProxy();People people = proxy.getInstance(People.class);people.setId(23);System.out.println(people.getId());}}class People {private int id;private String username;private int age;public int getId() {System.out.println("擷取id");return id;}public void setId(int id) {System.out.println("給id賦值");this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}}
java動態代理(JDK和cglib)