代理模式的优点:
- 代理模式能将代理对象和真实被调用的目标对象分离
- 在一定的程度降低系统的耦合性,扩展性好
- 可以起到保护目标对象的作用
- 可以增强目标对象的功能
代理模式的缺点
- 代理模式造成系统设计类的数量增加
- 在客户端和目标对象中增加一个代理对象,会导致请求处理速度变慢
- 增加系统的复杂度
静态代理和动态代理的本质区别
- 静态代理只能通过手动完成代理操作,如果被代理类增加的新的方法,代理类需要同步增加,违背的开闭原则
- 动态代理采用在运行时动态生成代码的方式,取消了对被代理类的扩展限制,遵循开闭原则
- 若动态代理要对目标代理的增加逻辑进行扩展,结合策略模式,只需要新增策略变可以完成,无需修改代理类的代码
CGLib 和 JDK 动态代理对比
- JDK动态代理实现了被代理对象的接口,CGLib 代理继承了被代理对象
- JDK动态代理和CGLib代理都是在运行期生成字节码文件,JDK动态代理直接写Class字节码,CGLib代理是使用ASM框架写Class字节码,CGLib代码实现更复杂,生成的代码里类比JDK动态代理效率低
- JDK动态代理调用代理方法是通过反射机制调用的,CGLib代理是通过FastClass 机制直接调用方法的,CGLib代理的执行效率高
接下里分别使用JDK动态代理 和 CGLib 实现业务场景
JDK 动态代理生成对象的步骤:
- 获取被代理对象的引用,并通过反射获取它所有的接口
- JDK动态代理类生成一个新的类,同时新的类要实现被代理类实现的所有接口
- 动态生成java代码,新加的业务逻辑方法由一定的逻辑代码调用
- 编译生成新的java代码.class 文件
- 重新加载到JVM中
JDK 动态代理
创建一个人类的接口 person
/**
* @Author Lxq
* @Date 2020/3/24 17:21
* @Version 1.0
*/
public interface Person {
public void findLove();
}
创建一个单身客户类 Customer
/**
* @Author Lxq
* @Date 2020/3/24 17:31
* @Version 1.0
* 单身客户类
*/
public class Customer implements Person{
@Override
public void findLove() {
System.out.println("身高180cm");
System.out.println("高富帅");
System.out.println("有8块腹肌");
}
}
媒婆的代理类 JDKMeipo
/**
* @Author Lxq
* @Date 2020/3/24 17:24
* @Version 1.0
* JDK动态代理
*/
public class JDKMeipo implements InvocationHandler {
// 被代理的对象,把引用保存下来
private Object target;
public Object getInstance(Object target) {
this.target = target;
Class<?> clazz = target.getClass();
return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object invoke = method.invoke(this.target, args);
after();
return invoke;
}
private void before(){
System.out.println("我是媒婆:我要给你找对象,现在确认一下你的要求");
System.out.println("开始配对");
}
private void after(){
System.out.println("如何合适,留下联系方式");
}
}
测试代理:
/**
* @Author Lxq
* @Date 2020/3/24 16:17
* @Version 1.0
*/
public class Test {
public static void main(String[] args) {
Person person = (Person) new JDKMeipo().getInstance(new Customer());
person.findLove();
}
}
CGLib 代理
CGLMeipo 代理类
/**
* @Author Lxq
* @Date 2020/3/24 17:37
* @Version 1.0
*/
public class CGLMeipo implements MethodInterceptor {
public Object getInStance(Class<?> clazz) {
Enhancer enhancer = new Enhancer();
// 要把那个设置生效为即将生成的新的父类
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
// 业务的增强
before();
Object obj = methodProxy.invokeSuper(o, objects);
after();
return obj;
}
private void before(){
System.out.println("我是媒婆:我要给你找对象,现在确认一下你的要求");
System.out.println("开始配对");
}
private void after(){
System.out.println("如何合适,留下联系方式");
}
}
测试代理
/**
* @Author Lxq
* @Date 2020/3/24 16:17
* @Version 1.0
*/
public class Test {
public static void main(String[] args) {
Customer customer = (Customer) new CGLMeipo().getInStance(Customer.class);
customer.findLove();
}
}