优点:
职责清晰:房东收钱,中介去找人,租客住宿
高扩展性:中介可以以任何形式宣传
智能化:中介可以过滤租客
缺点:
降低效率
增加复杂度
技术方案:jdk动态代理,cglib动态代理
jdk动态代理
1.被代理的对象必须要实现一个接口
2.代理需要实现InvocationHandler
3.代理过程在invoke中实现,中介处理业务的过程
4.创建代理对象Proxy.newProxyInstance实现,客户端调用
/**
* 被代理类房东接口
*/
public interface LandlordService {
/**
* 收租
*/
public void rentCollection(String tenantName,String intermediary);
}
/**
* 具体被代理类B房东
*/
public class BLandlordServiceImpl implements LandlordService{
public void rentCollection(String tenantName,String intermediary) {
System.out.println(intermediary+"缴纳"+tenantName+"租客的房租"+"给B房东");
}
}
/**
* 中介
*/
public class Intermediary implements InvocationHandler {
private Object intermediary;
public Intermediary(Object intermediary) {
this.intermediary = intermediary;
}
/**
* @param proxy 代理对象------>在内存中
* @param method 代理方法
* @param args 代理方法的参数
* @return
* @throws Throwable
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("befor");
method.invoke(intermediary, args);
System.out.println("after");
return null;
}
}
import java.lang.reflect.Proxy;
/**
* 1.被代理的对象必须要实现一个接口,BLandlordServiceImpl
* 2.代理需要实现InvocationHandler,中介
* 3.代理过程在invoke中实现,中介处理业务的过程
* 4.创建代理对象Proxy.newProxyInstance实现,客户端调用
*/
public class JdkDynamicAgentTest {
public static void main(String[] args) {
//创建被代理类
LandlordService landlord = new BLandlordServiceImpl();
LandlordService landlordProxy = (LandlordService) Proxy.newProxyInstance(
//被代理的类加载器
BLandlordServiceImpl.class.getClassLoader(),
//被代理类实现的所有接口
BLandlordServiceImpl.class.getInterfaces(),
//代理类
new Intermediary(landlord));
landlordProxy.rentCollection("租客花花", "链家中介小王");
}
}
cglib动态代理
底层是基于jdk实现,只是做了一些优化,被代理对象只要不是最终类就可以了,CGLIB会让生成的代理类继承被代理类,并在代理类中对代理方法进行强化处理(前置处理、后置处理等)。
1.代理过程实现CallBack(MethodInterceptor是CallBack的子接口)接口中的invoike实现
2.通过EnHancer来创建代理对象
/**
* 被代理类房东C
*/
public class CLandlordService {
public void rentCollection(String tenantName,String intermediary) {
System.out.println(intermediary+"缴纳"+tenantName+"租客的房租"+"给C房东");
}
}
import java.lang.reflect.Method;
/**
* 代理类
*/
public class Intermediary implements MethodInterceptor {
/**
*
* @param o cglib生成的代理对象
* @param method cglib生成的代理对象
* @param objects 方法入参
* @param methodProxy 代理方法
* @return
* @throws Throwable
*/
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("befor");
methodProxy.invokeSuper(o,objects);
System.out.println("after");
return null;
}
}
import org.springframework.cglib.core.DebuggingClassWriter;
import org.springframework.cglib.proxy.Enhancer;
/**
* 底层是基于jdk实现,只是做了一些优化
* JDK代理要求被代理的类必须实现接口,有很强的局限性。
* 而CGLIB动态代理则没有此类强制性要求。
* 简单的说,CGLIB会让生成的代理类继承被代理类,并在代理类中对代理方法进行强化处理(前置处理、后置处理等)。
* 在CGLIB底层,其实是借助了ASM这个非常强大的Java字节码生成框架。
*/
public class cglibTest {
public static void main(String[] args) {
// 代理类class文件存入本地磁盘方便我们反编译查看源码
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\project\\test\\mygithub\\design-pattern\\code");
// 通过CGLIB动态代理获取代理对象的过程
Enhancer enhancer = new Enhancer();
// 设置enhancer对象的父类
enhancer.setSuperclass(CLandlordService.class);
//设置回调函数
enhancer.setCallback(new Intermediary());
// 创建代理对象
CLandlordService cLandlordService = (CLandlordService) enhancer.create();
// 通过代理对象调用目标方法
cLandlordService.rentCollection("租客花花","链家小王");
}
}
附赠静态代理
/**
* 被代理类房东接口
*/
public interface LandlordService {
/**
* 收租
*/
public void rentCollection(String tenantName,String intermediary);
}
/**
* 具体被代理类A房东
*/
public class ALandlordServiceImpl implements LandlordService{
public void rentCollection(String tenantName,String intermediary) {
System.out.println(intermediary+"缴纳"+tenantName+"租客的房租"+"给A房东");
}
}
/**
* 中介
*/
public class Intermediary implements LandlordService {
private LandlordService landlordService;
public Intermediary(LandlordService landlordService){
this.landlordService=landlordService;
}
public void rentCollection(String tenantName, String intermediary) {
System.out.println("befor");
landlordService.rentCollection(tenantName,intermediary);
System.out.println("after");
}
}
/**
* 1.代理类要实现被代理类实现的接口
* 2.代理类中有被代理类的引用
* 3.代理类在实例化时将被代理类的引用初始化
*/
public class StaticAgentTest {
public static void main(String[] args) {
LandlordService aLandlord = new ALandlordServiceImpl();
LandlordService aLandlordService = new Intermediary(aLandlord);
aLandlordService.rentCollection("租客花花","链家中介小王");
}
}
静态代理的缺点:代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为每一种方法都进行代理,静态代理在程序规模稍大时就无法胜任了。
动态代理与静态代理相比较,最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理
cglib动态代理和jdk动态代理最大的优点是,cglib的被代理类不用实现接口