什么是动态代理?
接着之前的故事,我们继续。我们在通过代购帮我们购买了好多次物品以后,代购现在越来越有钱了,代购的商品种类也更加丰富,他便自己开了一家代购公司D,这个时候我们如果想要去通过代购去买一件商品,就不在会是每一次都是同一个人去接待我们,可能是D公司的小刘美女业务员、也可能是小王帅哥业务员。即:动态代理就是,同一个服务由不同的实例去帮我们实现。
JDK动态代理类图
JDK动态代理是如何实现的?
1、动态代理是由Proxy Java反射类提供实例创建的调派,由Proxy.newProxyInstance()方法帮我们创建对应的实例对象。
2、通过InvocationHandler接口中的invoke方法进行调用、增强、转发实现业务。
为什么JDK中类的实例化以及业务实现如此复杂?
遵循Java单一原则,一个类或者一个接口只负责唯一职责,尽量设计出功能单一的接口。
代码示例
A抽象对象
public interface ASellService {
void sale(String name);
}
A真实对象(商家A)
public class AMerchantServiceImplA implements ASellService {
@Override
public void sale(String name) {
System.out.println(name + "购买了A商品");
}
}
B抽象对象
public interface BSellService {
void sale(String name);
}
B真实对象(商家B)
public class BMerchantServiceImpl implements BSellService {
@Override
public void sale(String name) {
System.out.println(name + "购买了B商品");
}
}
JDK动态代理类(代理公司)
public class DCompany implements InvocationHandler {
// 代理对象需要包含真实对象,为提升真实对象的复用性,则使用Object接受
private Object objFactory;
public Object getObjFactory(){
return objFactory;
}
public void setObjFactory(Object objFactory){
this.objFactory = objFactory;
}
// 使用JDK代理类获取代理对象
public Object getProxyInstance(){
return Proxy.newProxyInstance(objFactory.getClass().getClassLoader(), objFactory.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 进行业务增强
System.out.println("JDK动态代理对业务进行了增强处理");
// 通过反射调用方法本身
Object invoke = method.invoke(objFactory, args);
System.out.println("JDK动态代理对业务进行了增强处理结束");
return invoke;
}
}
测试类
public class DynamicProxyTest {
public static void main(String[] args) {
// A商品卖家
ASellService A = new AMerchantServiceImplA();
// B商品卖家
BSellService B = new BMerchantServiceImpl();
// 购买者
String customerName = "张三";
// 代购公司
DCompany dCompany = new DCompany();
dCompany.setObjFactory(A);
ASellService AProxyInstance = (ASellService) dCompany.getProxyInstance();
System.out.println("业务员"+AProxyInstance.getClass()+"接待"+customerName);
AProxyInstance.sale(customerName);
System.out.println("--------------------------------------------------------------");
dCompany.setObjFactory(B);
BSellService BProxyInstance = (BSellService) dCompany.getProxyInstance();
System.out.println("业务员"+BProxyInstance.getClass()+"接待"+customerName);
BProxyInstance.sale(customerName);
}
}
执行结果
我们可以清晰的看到JDK动态代理执行后打印的结果,以及Proxy动态调派帮我们由不同的代理对象$Proxy X实例化真实对象。
总结
1、动态代理无需真实对象的差异及数量可以统一的由代理方法帮我们创建对应的真实对象实例,并引用其中的方法。
2、动态代理属于编译期代理,及运行期代理。此特点则体现了实例对象的创建由Proxy进行调派完成实例化。
如果觉着不错可以关注公众号:Java秃头猿,专注于项目实际开发技术分享。
java动态代理