代理模式
代理模式是一種結(jié)構(gòu)型設(shè)計模式,它通過創(chuàng)建一個代理對象來控制對真實對象的訪問。這種模式可以用于提供額外的功能操作,或者擴(kuò)展目標(biāo)對象的功能。
在代理模式中,代理對象與真實對象實現(xiàn)相同的接口,以便在任何地方都可以使用相同的接口來調(diào)用真實對象的方法。這樣做的好處是可以在不改變原始代碼的情況下,增加或修改代碼的行為。
根據(jù)創(chuàng)建代理對象的方式和時機(jī),代理模式可以被分為靜態(tài)代理、動態(tài)代理等類型。其中,靜態(tài)代理是由程序員在編譯時期就定義好的代理類,而動態(tài)代理則是在程序運行時期通過Java反射機(jī)制動態(tài)生成的。
在實際生活中,有許多應(yīng)用了代理模式的場景,例如租房、賣房、家政等業(yè)務(wù),通常由中介機(jī)構(gòu)作為代理來進(jìn)行操作。
靜態(tài)代理
靜態(tài)代理在編譯期間就已經(jīng)確定代理類的代碼。具體來說,要實現(xiàn)靜態(tài)代理需要手動編寫代理類的代碼,因此這種方式的靈活性相對較差,但由于代理類是直接編寫的,所以其運行效率較高。
首先定義購房者的行為
/**
* 購房者
*
* @author LionLi
*/
public interface Homebuyer {
/**
* 需求
*/
String need();
/**
* 購買
*/
void buy();
}
定義真實購房者
/**
* 購房者 張三
*
* @author LionLi
*/
public class Zhangsan implements Homebuyer {
/**
* 需求
*/
@Override
public String need() {
String need = "100平以上三室兩廳兩衛(wèi)";
System.out.println("張三: " + need);
return need;
}
/**
* 購買
*/
@Override
public void buy() {
System.out.println("張三: 我已付款");
}
}
/**
* 購房者 王五
*
* @author LionLi
*/
public class Wangwu implements Homebuyer {
/**
* 需求
*/
@Override
public String need() {
String need = "70平左右兩室一廳";
System.out.println("王五: " + need);
return need;
}
/**
* 購買
*/
@Override
public void buy() {
System.out.println("張三: 我已付款");
}
}
定義房產(chǎn)中介
/**
* 房產(chǎn)中介代理人
*
* @author LionLi
*/
public class HouseAgentProxy implements Homebuyer {
private Homebuyer homebuyer;
public HouseAgentProxy(Homebuyer homebuyer) {
this.homebuyer = homebuyer;
}
@Override
public String need() {
System.out.println("中介: 你對房子有什么需求 放心交給我");
String need = homebuyer.need();
System.out.println("中介: 尋找房源中........");
System.out.println("中介: 尋找房源中........");
System.out.println("中介: 尋找房源中........");
String str = "中介: 為您找到" + need + "的房子";
System.out.println(str);
return str;
}
@Override
public void buy() {
System.out.println("中介: 請支付購買房子");
homebuyer.buy();
System.out.println("中介: 合同生效中.....");
System.out.println("中介: 房證辦理中.....");
System.out.println("中介: 恭喜您 這套房子屬于您了");
}
}
測試
/**
* @author LionLi
*/
public class Test {
public static void main(String[] args) {
Homebuyer zhangsan = new Zhangsan();
HouseAgentProxy agent1 = new HouseAgentProxy(zhangsan);
agent1.need();
agent1.buy();
System.out.println("-----------------------------");
Homebuyer wangwu = new Wangwu();
HouseAgentProxy agent2 = new HouseAgentProxy(wangwu);
agent2.need();
agent2.buy();
}
}
兩位購房者分別根據(jù)需求在中介的帶領(lǐng)下買到了房子 真是可喜可賀啊
動態(tài)代理
動態(tài)代理允許在運行時動態(tài)地創(chuàng)建代理對象。代理對象可以在調(diào)用實際對象的方法前后執(zhí)行一些額外的操作,比如日志記錄、權(quán)限檢查等。
動態(tài)代理的實現(xiàn)方式有兩種:基于接口和基于繼承。基于接口的方式是最常用的,它使用Java的反射機(jī)制來實現(xiàn)代理對象。基于繼承的方式則需要創(chuàng)建一個實現(xiàn)了目標(biāo)類接口的子類,并重寫其中的方法。
優(yōu)點: 可以降低系統(tǒng)的耦合度,提高代碼的可維護(hù)性和可擴(kuò)展性。
缺點: 需要使用反射機(jī)制,性能比靜態(tài)代理略低。
首先定義購房者的行為與實際購房者
使用上方代碼不變
定義房產(chǎn)中介
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 動態(tài)房產(chǎn)中介代理人
*
* @author LionLi
*/
public class DynamicHouseAgentProxy implements InvocationHandler {
private Homebuyer homebuyer;
public Homebuyer getInstance(Homebuyer homebuyer) {
this.homebuyer = homebuyer;
return (Homebuyer) Proxy.newProxyInstance(homebuyer.getClass().getClassLoader(), homebuyer.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("need")) {
System.out.println("中介: 你對房子有什么需求 放心交給我");
String need = (String) method.invoke(homebuyer, args);
System.out.println("中介: 尋找房源中........");
System.out.println("中介: 尋找房源中........");
System.out.println("中介: 尋找房源中........");
String str = "中介: 為您找到" + need + "的房子";
System.out.println(str);
return str;
} else if (method.getName().equals("buy")) {
System.out.println("中介: 請支付購買房子");
Object invoke = method.invoke(homebuyer, args);
System.out.println("中介: 合同生效中.....");
System.out.println("中介: 房證辦理中.....");
System.out.println("中介: 恭喜您 這套房子屬于您了");
return invoke;
}
return null;
}
}
測試
/**
* @author LionLi
*/
public class Test {
public static void main(String[] args) {
DynamicHouseAgentProxy agent = new DynamicHouseAgentProxy();
Homebuyer zhangsan = new Zhangsan();
Homebuyer proxy1 = agent.getInstance(zhangsan);
proxy1.need();
proxy1.buy();
System.out.println("-----------------------------");
Homebuyer wangwu = new Wangwu();
Homebuyer proxy2 = agent.getInstance(wangwu);
proxy2.need();
proxy2.buy();
}
}
結(jié)果不變 兩位購房者成功買到房子
Cglib動態(tài)代理
其他代碼不變只變更中介類
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* 動態(tài)房產(chǎn)中介代理人
*
* 這里由于cglib已經(jīng)不支持jdk17了 所以我們使用spring內(nèi)部自帶的cglib工具
*
* @author LionLi
*/
public class DynamicHouseAgentProxy implements MethodInterceptor {
public Homebuyer getInstance(Homebuyer homebuyer) {
Enhancer enhancer = new Enhancer();
// 設(shè)置繼承父類
enhancer.setSuperclass(homebuyer.getClass());
// 設(shè)置回調(diào)
enhancer.setCallback(this);
return (Homebuyer) enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
if (method.getName().equals("need")) {
System.out.println("中介: 你對房子有什么需求 放心交給我");
String need = (String) proxy.invokeSuper(obj, args);
System.out.println("中介: 尋找房源中........");
System.out.println("中介: 尋找房源中........");
System.out.println("中介: 尋找房源中........");
String str = "中介: 為您找到" + need + "的房子";
System.out.println(str);
return str;
} else if (method.getName().equals("buy")) {
System.out.println("中介: 請支付購買房子");
Object invoke = proxy.invokeSuper(obj, args);
System.out.println("中介: 合同生效中.....");
System.out.println("中介: 房證辦理中.....");
System.out.println("中介: 恭喜您 這套房子屬于您了");
return invoke;
}
return null;
}
}
Spring中代理模式的應(yīng)用
要說起Spring中的代理模式 要首當(dāng)其沖的肯定是AOP了 接下來我們來看看在AOP中是如何使用代理模式的
這里涉及到一個注解 學(xué)過AOP的都知道 如果需要開啟AOP那么需要增加這個注解
通過搜索找到 AspectJAutoProxyRegistrar
類, 該方法的作用就是往Spring容器中添加一個 BeanDefinition
類型為 AnnotationAwareAspectJAutoProxyCreator
用于創(chuàng)建代理對象
接下來我們進(jìn)入 AnnotationAwareAspectJAutoProxyCreator
看看是如何創(chuàng)建代理的
由于 AnnotationAwareAspectJAutoProxyCreator
中并沒有創(chuàng)建代理的方法 那么我們只能向上去父類里找, 通過不斷的探索在 AnnotationAwareAspectJAutoProxyCreator
-> AspectJAwareAdvisorAutoProxyCreator
-> AbstractAdvisorAutoProxyCreator
-> AbstractAutoProxyCreator
抽象類 AbstractAutoProxyCreator
中找到了 createProxy
方法
此方法是bean初始化的前置處理器 postProcessBeforeInstantiation
中使用的, 也就是說bean在初始化之前, 代理對象就已經(jīng)創(chuàng)建好了
進(jìn)入 createProxy
方法
進(jìn)入 buildProxy
方法
這里我們可以看出 實際的代理對象是通過 ProxyFactory
工廠的 getProxyClass
與 getProxy
兩個方法創(chuàng)建的
我們來看一下這兩個方法具體實現(xiàn)
通過 getProxyClass
方法一直往下點 找到最終創(chuàng)建方法 DefaultAopProxyFactory#createAopProxy
為止
最后我們來分析最終是如何創(chuàng)建代理對象的文章來源:http://www.zghlxwxcb.cn/news/detail-807124.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-807124.html
到了這里,關(guān)于設(shè)計模式 代理模式(靜態(tài)代理 動態(tài)代理) 與 Spring Aop源碼分析 具體是如何創(chuàng)建Aop代理的的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!