3.靜態代理&動態代理&CGlib
代理模式
1 代理的概念
代理的作用:為了實現在不更改被代理類的基礎上,對被代理類的功能進行擴充套件。
代理物件:對被代理物件的功能進行擴充套件(中介)
目標物件:被代理物件。
原則:代理物件,代理的是目標物件,不能有更多的功能。
2 實現方式
2.1 靜態代理
2.1.1 靜態代理的要求
- 代理類和被代理類必須實現相同的介面。
- 代理類中存在被代理類的物件的引用。
2.1.2 程式碼實現
package com.atguigu.proxytest;
/**
* 靜態代理舉例
* 特點:代理類和被代理類在編譯期間就已經確定了。
*
* @author 龍
*/
interface ClothFactory {
/**
* 生產衣服的方法
*/
void produceCloth();
}
/**
* 代理類
*/
class ProxyClothFactory implements ClothFactory {
/**
* 使用被代理類物件進行例項化
*/
private ClothFactory factory;
public ProxyClothFactory(ClothFactory factory) {
this.factory = factory;
}
@Override
public void produceCloth() {
System.out.println("代理工廠進行一些準備工作");
factory.produceCloth();
System.out.println("代理工廠進行一些後續的收尾工作");
}
}
/**
* 被代理類
*/
class NikeClothFactory implements ClothFactory {
@Override
public void produceCloth() {
System.out.println("Nike生產了一批運動服裝");
}
}
/**
* @author 龍
*/
public class StaticProxyTest {
public static void main(String[] args) {
NikeClothFactory nike = new NikeClothFactory();
ProxyClothFactory proxyClothFactory = new ProxyClothFactory(nike);
proxyClothFactory.produceCloth();
}
}
2.1.3 存在的問題
- 代理類和被代理類必須實現相同的介面。
- 代理類和被代理類在編譯時期,就已經確定。
- 只可以擴充套件介面中的方法。
- 一旦介面增加方法,就需要對目標物件和代理類進行功能擴充套件。
2.2 動態代理
2.2.1 要求
- 必須實現一個介面
- 代理類存在一個
2.2.2 程式碼實現
package com.atguigu.proxytest;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author 龍
*/
interface Human {
/**
* 能力
*
* @return :能力
*/
String getBelief();
/**
* 吃食物
*
* @param food :食物
*/
void eat(String food);
}
/**
* 超人類
*/
class SuperMan implements Human {
@Override
public String getBelief() {
return "I can Fly";
}
@Override
public void eat(String food) {
System.out.println("我喜歡吃" + food);
}
}
/**
* 根據被代理類建立代理類物件
*/
class ProxyFactory {
public static Object getProxyInstance(Object obj) {
//呼叫此方法,返回一個代理類物件
MyInvocationHandler handler = new MyInvocationHandler();
handler.bind(obj);
Object o = Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), handler);
return o;
}
}
class MyInvocationHandler implements InvocationHandler {
//被代理類物件
private Object object;
public void bind(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//當我們通過代理類物件呼叫方法A的時候就會呼叫該方法,將被代理類要求執行的方法a的功能就生命在invoke()中
HumanUtil util = new HumanUtil();
util.method1();
//類似於AOP:面向切面程式設計。
Object invoke = method.invoke(object, args);
util.method2();
return invoke;
}
}
class HumanUtil {
public void method1() {
System.out.println("通用方法1");
}
public void method2() {
System.out.println("通用方法2");
}
}
/**
* 存在的問題:
* 一:如何根據載入到記憶體中的被代理類,動態的建立一個代理類及其物件。
* 二:當通過代理類的物件呼叫方法時,如何動態的去呼叫被代理的同名方法
*
* @author 龍
*/
public class ProxyTest {
public static void main(String[] args) {
SuperMan superMan = new SuperMan();
//此時為代理類物件
Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan);
//會自動的呼叫被代理類中同名的方法。
proxyInstance.eat("四川麻辣燙");
String belief = proxyInstance.getBelief();
System.out.println(belief);
NikeClothFactory nikeClothFactory = new NikeClothFactory();
ClothFactory proxyInstance1 = (ClothFactory) ProxyFactory.getProxyInstance(nikeClothFactory);
proxyInstance1.produceCloth();
}
}
2.2.3 動態代理
優點:
- 不需要我們手動的建立代理類,只需要編寫一個動態處理器,真正的代理物件由JDK在執行的時候為我們動態的建立。
- 減少了對業務介面的依賴,降低了耦合度。
缺點:
- 無法擺脫對介面的依賴,必須要實現一個介面,這是由java的繼承機制註定了這些被動態代理類必須實現一個介面。
2.3 cglib
2.3.1 出現背景
因為JDK要求動態代理必須實現通過介面定義業務方法,對於沒有介面的類,如何實現動態代理,這就是CGlib要實現的。CGLib採用了非常底層的位元組碼技術,其原理是通過位元組碼技術為一個類建立子類,並在子類中採用方法攔截的技術攔截所有父類方法的呼叫,順勢織入橫切邏輯。但因為採用的是繼承,所以不能對final修飾的類進行代理。JDK動態代理與CGLib動態代理均是實現Spring AOP的基礎。Cglib又被稱為:子類代理。
2.3.2 程式碼實現
package com.atguigu.proxytest;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CGLibTest {
/*cglib代理:子類代理
* 特點建立目標類的子類 通過重寫父類方法來實現目標類功能的控制
* */
public static void main(String[] args) {
Teacher t=new Teacher(31, "韓寒");//定義目標類物件
ZiProxyFactroy factroy=new ZiProxyFactroy(t);//建立工廠類物件並關聯目標類物件
//呼叫工廠類物件的getInstance方法動態獲取目標類的子類物件
Teacher proxy=(Teacher)factroy.getInstance();
proxy.hehe();
proxy.teach();
}
}
//1 建立子類物件工廠類 實現MethodInterceptor
class ZiProxyFactroy implements MethodInterceptor{
//2 定義成員變數記錄目的物件
private Object target;
public ZiProxyFactroy(Object target) {//通過構造方法關聯目標物件
this.target = target;
}
//3 目標物件的方法被呼叫時 intercept方法就會執行
public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println(method.getName()+"+++++方法被呼叫前的域處理程式碼");
Object result=method.invoke(target, args);
System.out.println(method.getName()+"-----方法被呼叫後的後處理程式碼");
return result;
}
//4 定義一個動態生成目標類的子類物件
public Object getInstance() {
Enhancer er=new Enhancer(); //4.1 建立加強工具類
er.setSuperclass(target.getClass()); //4.2 指定要加強的父類(目標類)
er.setCallback(this); //4.3 設定回撥函式
return er.create(); //4.4 返回一個子類物件
}
}
//5 定義目標類
class Teacher{
int age; String name;
public Teacher(int age, String name) {
this.age = age;
this.name = name;
}
public Teacher() {
super();
}
void hehe() {
System.out.println("老師::"+age+","+name);
}
void teach() {
System.out.println(name+"正在教書!!!");
}
}
注:需要匯入jar包 spring-core-4.3.18.RELEASE.jar
相關文章
- Java代理(jdk靜態代理、動態代理和cglib動態代理)JavaJDKCGLib
- 代理模式詳解:靜態代理、JDK動態代理與Cglib動態代理模式JDKCGLib
- 靜態代理和動態代理(jdk/cglib)詳解JDKCGLib
- CGLib 動態代理CGLib
- 由《尋秦記》說代理模式(靜態,動態,CGLib)模式CGLib
- 靜態代理和動態代理
- JAVA 靜態代理 & 動態代理Java
- JDK動態代理和 CGLIB 代理JDKCGLib
- JDK動態代理和CGLib代理JDKCGLib
- java靜態代理和動態代理Java
- 動態代理-cglib分析CGLib
- (轉)Java動態代理與CGLib代理JavaCGLib
- AOP之靜態代理VS動態代理
- spring aop原理 JDK動態代理和CGLIB動態代理SpringJDKCGLib
- Java進階之 JDK動態代理與Cglib動態代理JavaJDKCGLib
- CGlib動態代理複習CGLib
- 輕鬆理解 Java 靜態代理/動態代理Java
- Java中的靜態代理和動態代理Java
- 靜態代理、動態代理與Mybatis的理解MyBatis
- 你必須會的 JDK 動態代理和 CGLIB 動態代理JDKCGLib
- 深入理解靜態代理與JDK動態代理JDK
- Java基礎系列-靜態代理和動態代理Java
- JAVA學習篇--靜態代理VS動態代理Java
- Java動態代理(JDK和cglib)JavaJDKCGLib
- cglib動態代理和jdk動態代理的區別與應用CGLibJDK
- 《Proxy系列專題》:代理模式(靜態、JDK、CGLib)模式JDKCGLib
- Java代理之靜態代理Java
- 最詳細的代理講解--JDK動態代理和cglib代理JDKCGLib
- CGLib動態代理原理及實現CGLib
- 【深度思考】聊聊CGLIB動態代理原理CGLib
- 聊聊cglib動態代理遇到的坑CGLib
- CGlib動態代理-簡單介紹CGLib
- 設計模式之cglib動態代理設計模式CGLib
- Spring動態代理的生成-如何判斷是使用JDK動態代理還是CGlib代理SpringJDKCGLib
- java執行原理、靜態代理和動態代理區分Java
- Java靜態代理Java
- 代理模式-靜態代理解讀模式
- Java 靜態代理和動態代理的使用及原理解析Java