代理模式
为其他对象提供一个代理,以控制这个对象的访问,在客户端与目标对象之间起到中介作用,属于结构型模式
作用
保护和增强目标对象
静态代理
显示代理目标对象,通过硬编码完成代理工作,不适用于目标类型较多的场景
动态代理
对目标类实现统一增强,与静态代理一样,都是生成目标类的增强类来完成功能,不过静态代理使用硬编码方式,动态代理通过反射等技术动态的生成代理对象,代理逻辑与业务逻辑是互相独立的,没有耦合,代理1个类或100个类要做的事情没有任何区别
java JDK的动态代理(Proxy类)
下面以房产中介与房屋拥有者为例
- 必须实现同一个的目标接口
// 房屋拥有者
public interface HomeOwner {
public void lookHome();
public void sendHome();
}
- 实现两个房屋拥有者
public class LiSi implements HomeOwner{
@Override
public void lookHome() {
System.out.println("星期天可以看");
}
@Override
public void sendHome() {
System.out.println("50w可以卖");
}
}
public class ZhangSan implements HomeOwner{
@Override
public void lookHome() {
System.out.println("20好可以来看房");
}
@Override
public void sendHome() {
System.out.println("100万可以卖房");
}
}
- 实现房产中介(核心)
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class HomeProxy implements InvocationHandler {
HomeOwner pHomeOwner;
public HomeOwner getInstance(HomeOwner homeOwner){
this.pHomeOwner = homeOwner;
Class clazz = pHomeOwner.getClass();
return (HomeOwner)Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object res = method.invoke(pHomeOwner, args);
after();
return res;
}
public void before(){
System.out.println("商量时间");
}
public void after(){
System.out.println("收佣金");
}
}
- 测试类
// 中介可以完美代理不同的人
public class Test {
public static void main(String[] args) {
HomeOwner homeProxy = new HomeProxy().getInstance(new ZhangSan());
homeProxy.lookHome();
homeProxy.sendHome();
HomeOwner homeProxy1 = new HomeProxy().getInstance(new LiSi());
homeProxy1.lookHome();
homeProxy1.sendHome();
}
}
基于Cglib实现动态代理(因为JDK代理必须要实现共同接口)
- 引入依赖
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
- 实现代理对象(基于继承,生成子类)
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibHomeProxy 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 res = methodProxy.invokeSuper(o, objects);
after();
return res;
}
public void before(){
System.out.println("商量时间");
}
public void after(){
System.out.println("收佣金");
}
}
- 测试
public class Test {
public static void main(String[] args) {
LiSi liSiProxy = (LiSi) new CglibHomeProxy().getInstance(LiSi.class);
liSiProxy.lookHome();
}
}