//抽象接口 ,描述了服務提供者的行爲 代理接口
public interface ManToolsFactory {
void saleManTools(String size);
}
//抽象接口 ,描述了服務提供者的行爲 代理接口
public interface WomanToolsFactory {
void saleWomanTools(float length);
}
/**
* 靜態代理和動態代理的區別
* 靜態代理通常只代理一個類,動態代理是代理一個接口下的多個實現類。
* 靜態代理要事先知道要代理的是什麼,而動態代理不知道具體要代理的是什麼東西,只有在運行時才知道。
* 動態代理是實現jdk 裏的invocationHandler接口的invoke 方法,但注意的是代理的是接口,
* 也就是你的實現類必須要實現接口,通過proxy裏的 newProxyInstance得到代理對象。
*
* 靜態代理優點:
* 業務類只需要關注業務邏輯本身,保證了業務類的重用性,這是代理共有的優點。
* 缺點:
* 1,代理對象的一個接口只服務於一種類型的對象。如果要代理的方法很多。要爲每一種方法都進行代理。
* 2,如果接口增加一個方法,除了所有實現類需要實現這個方法外,所有代理類也需要實現此方法,增加了代碼維護的複雜性。
*/
//真正提供服務的類 具體業務邏輯類
public class AaFactory implements ManToolsFactory {
@Override
public void saleManTools(String size) {
System.out.println("根據你的需求提供了Size爲"+size+"手機");
}
}
/**
* 靜態代理和動態代理的區別
* 靜態代理通常只代理一個類,動態代理是代理一個接口下的多個實現類。
* 靜態代理要事先知道要代理的是什麼,而動態代理不知道具體要代理的是什麼東西,只有在運行時才知道。
* 動態代理是實現jdk 裏的invocationHandler接口的invoke 方法,但注意的是代理的是接口,
* 也就是你的實現類必須要實現接口,通過proxy裏的 newProxyInstance得到代理對象。
*
* 靜態代理優點:
* 業務類只需要關注業務邏輯本身,保證了業務類的重用性,這是代理共有的優點。
* 缺點:
* 1,代理對象的一個接口只服務於一種類型的對象。如果要代理的方法很多。要爲每一種方法都進行代理。
* 2,如果接口增加一個方法,除了所有實現類需要實現這個方法外,所有代理類也需要實現此方法,增加了代碼維護的複雜性。
*/
public class BbFactory implements WomanToolsFactory{
@Override
public void saleWomanTools(float length) {
System.out.println("根據你的需求,定製長度爲"+length+"的手機");
}
}
靜態代理對象
//代理對象,包含真實的對象,爲真實的對象的服務進行真強,和真實對象繼承於同一個接口
public class Chinar implements ManToolsFactory {
//被包含的真實對象
public ManToolsFactory factory;
public Chinar(ManToolsFactory factory){
super();
this.factory = factory;
}
@Override
public void saleManTools(String size) {
dosomeThingBefore();//前置真強
factory.saleManTools(size);
dosomeThingEnd();//後置增強
}
//售前服務
private void dosomeThingBefore(){
System.out.println("精美包裝,快遞一條龍服務");
}
//售後服務
private void dosomeThingEnd(){
System.out.println("根據你的需求,進行市場調研和分析");
}
}
靜態代理
/**
* 生成靜態代理類工廠
*/
public class SubjectStaticFactory {
//客戶類調用此工廠方法獲得代理對象。
//對客戶類來說,其並不知道返回的是代理類對象還是委託類對象。
public static ManToolsFactory getinstance(){
//具體實現業務邏輯類
ManToolsFactory factory = new AaFactory();
//我代理這個公司的產品 代理對象
Chinar chinar = new Chinar(factory);
return chinar;
// return new Chinar(new AaFactory());
}
}
靜態代理測試
/**
* 靜態代理測試類
*/
public class ZhanSan {
public static void main(String []args){
//靜態代理
ManToolsFactory factory = new AaFactory();
//我代理這個公司的產品
Chinar chinar = new Chinar(factory);
//調用該產品方法
chinar.saleManTools("20");
System.out.println("-----------------------------------------------------------");
//利用靜態代理工廠來調用
ManToolsFactory proxy = SubjectStaticFactory.getinstance();
proxy.saleManTools("22");
System.out.println("-----------------------------------------------------------");
}
}
動態代理
/**
* 動態測試類
*/
public class WangWu {
public static void main(String []args){
//動態代理 只增加接口和接口實現,代理類不需要修改代碼
//A代理公司
ManToolsFactory aFactory = new AaFactory();
//B代理公司
WomanToolsFactory bbFactory = new BbFactory();
//代購公司
Chinarui chinarui = new Chinarui();
//張三來找我要代購產品
chinarui.setFactory(aFactory);
System.out.println("-----------------------------------------------------------");
//1號業務員對這個行業收悉,派1號業務員爲他服務
ManToolsFactory chinarui1= (ManToolsFactory) chinarui.getProxyInstance();
chinarui1.saleManTools("21");
System.out.println("-----------------------------------------------------------");
// //張三朋友來找我,代購xxx產品
// chinarui.setFactory(bbFactory);
// //2號業務員對這個行業收悉,派2號業務員爲他服務
// WomanToolsFactory chinarui2= (WomanToolsFactory) chinarui.getProxyInstance();
// chinarui2.saleWomanTools(1.9F);
//
// ProxyUtil.generateClassFile(aFactory.getClass(),chinarui1.getClass().getSimpleName());
// ProxyUtil.generateClassFile(aFactory.getClass(),chinarui2.getClass().getSimpleName());
}
}
import sun.misc.FileURLMapper;
import sun.misc.ProxyGenerator;
import java.io.FileOutputStream;
import java.io.IOException;
public class ProxyUtil {
/**
* 將動態生成的2進制字節碼保存到硬盤中,
* @param classz 需要動態代理的類
* @param proxuyName 爲動態代理生成的類的名稱
*/
public static void generateClassFile(Class classz, String proxuyName){
//根據類信息和代理類名稱生成字節碼。
byte[] classFile = ProxyGenerator.generateProxyClass(proxuyName, new Class[]{classz});
String paths = classz.getResource(".").getPath();
System.out.println(paths);
FileOutputStream out = null ;
//保存到硬盤中
try{
out = new FileOutputStream(paths + proxuyName + ".class");
out.write(classFile);
out.flush();
}catch (Exception e){
e.printStackTrace();
}finally {
try{
out.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}