1. 代理模式概述
代理模式是一种比较好理解的设计模式。简单来说就是 我们使用代理对象来代替对真实对象(real object)的访问,这样就可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。
代理模式的主要作用是扩展目标对象的功能,比如说在目标对象的某个方法执行前后你可以增加一些自定义的操作。
代理模式分为静态代理与动态代理,动态代理又分为jdk动态代理与cglig动态代理。
代理模式使用场景很多,比如买房中介,代购等等都属于代理。
2. 代理模式实现
消费者接口类 Customer
/**
* 消费者接口类
*
* @author 20023262
* @date 2020/12/11
* @since 1.0
*/
public interface Customer {
/**
* 购物
*/
void shopping();
}
具体消费者 SingaporeCustomerImpl
/**
* 具体消费者
*
* @author 20023262
* @date 2020/12/11
* @since 1.0
*/
public class SingaporeCustomerImpl implements Customer {
@Override
public void shopping() {
System.out.println("【被代理者】 I am SingaporeCustomer");
}
}
静态代理类 CustomerProxy
/**
* 静态代理类
*
* 静态代理总结:
* 优点:可以做到在符合开闭原则的情况下对目标对象进行功能扩展。
* 缺点:我们得为每一个服务都得创建代理类,工作量太大,不易管理。同时接口一旦发生改变,代理类也得相应修改。
*
* @author 20023262
* @date 2020/12/11
* @since 1.0
*/
public class CustomerProxy implements Customer {
private Customer customer;
public CustomerProxy(Customer customer) {
this.customer = customer;
}
@Override
public void shopping() {
System.out.println("【静态代理】代购,购物前挑选...");
customer.shopping();
System.out.println("【静态代理】代购,购物后检验...");
}
}
JDK动态代理类 DynamicProxyHandler
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* JDK动态代理类
* 动态代理总结:虽然相对于静态代理,动态代理大大减少了我们的开发任务,同时减少了对业务接口的依赖,降低了耦合度。
*
* @author 20023262
* @date 2020/12/11
* @since 1.0
*/
public class DynamicProxyHandler implements InvocationHandler {
private Object object;
public DynamicProxyHandler(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("【jdk动态代理】代购,购物前挑选...");
Object result = method.invoke(object, args);
System.out.println("【jdk动态代理】代购,购物后检验...");
return result;
}
}
cglib动态代理类 CglibProxyHandler
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* cglib动态代理类
*
* @author 20023262
* @date 2020/12/11
* @since 1.0
*/
public class CglibProxyHandler implements MethodInterceptor {
private Object target;
public CglibProxyHandler(Object target) {
this.target = target;
}
/**
* 代理方法
*/
public Object getProxyInstance() {
//1. 工具类
Enhancer en = new Enhancer();
//2. 设置父类
en.setSuperclass(target.getClass());
//3. 设置回调函数
en.setCallback((MethodInterceptor) (o, method, args, methodProxy) -> {
System.out.println("【cglib动态代理】代购,购物前挑选...");
//Object obj = method.invoke(target, args);
Object obj = methodProxy.invokeSuper(o, args);
System.out.println("【cglib动态代理】代购,购物后检验...");
return obj;
});
//4. 创建子类(代理对象)
return en.create();
}
/**
* 以下方式会抛出异常:Exception in thread "main" java.lang.StackOverflowError
*/
public Object getInstance(Object object) {
target = object;
//增强类对象
Enhancer enhancer = new Enhancer();
//设置增强类型
enhancer.setSuperclass(this.target.getClass());
//设置回调函数
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("【cglib动态代理】代购,购物前挑选...");
Object result = proxy.invoke(obj, args);
System.out.println("【cglib动态代理】代购,购物后检验...");
return result;
}
}
代理测试类 ProxyTest
import org.junit.Test;
import java.lang.reflect.Proxy;
/**
* 代理测试类
*
* @author 20023262
* @date 2020/12/11
* @since 1.0
*/
public class ProxyTest {
@Test
public void proxyTest() {
System.out.println("--------------原类-------------------------");
Customer singaporeCustomer = new SingaporeCustomerImpl();
singaporeCustomer.shopping();
System.out.println("---------------静态代理类------------------");
CustomerProxy customerProxy = new CustomerProxy(new SingaporeCustomerImpl());
customerProxy.shopping();
System.out.println("---------------jdk动态代理类------------------");
Customer proxyCustomer = (Customer) Proxy.newProxyInstance(Customer.class.getClassLoader(), new Class[]{Customer.class}, new DynamicProxyHandler(new SingaporeCustomerImpl()));
proxyCustomer.shopping();
System.out.println("---------------cglib动态代理类------------------");
SingaporeCustomerImpl proxyCustomerImpl = (SingaporeCustomerImpl) new CglibProxyHandler(new SingaporeCustomerImpl()).getProxyInstance();
proxyCustomerImpl.shopping();
}
}