代理模式
通过代理对象访问目标对象,在不改变目标对象的情况下,对目标对象进行方法增强.
代理主要分以下三种情况:
- 静态代理
- JDK动态代理
- 使用cglib库实现动态代理
静态代理
1.定义一个接口
2.实现类
3.代理类
代码
1.定义接口
/**
* 售票窗口
*/
public interface ITicketOffice {
/**
* 出售火车票
* @param num 出售数量
*/
void saleTicket(int num);
}
2.实现类
/**
* 售票厅
*/
public class TicketOffice implements ITicketOffice{
@Override
public void saleTicket(int num) {
System.out.println("出售车票数 :"+num);
}
}
3.代理类
/**
* 代售点
*/
public class ProxyTicketOffice implements ITicketOffice {
/**
* 售票厅对象
*/
private TicketOffice ticketOffice;
public ProxyTicketOffice(TicketOffice ticketOffice) {
this.ticketOffice = ticketOffice;
}
@Override
public void saleTicket(int num) {
System.out.println("进入代售点");
ticketOffice.saleTicket(num);
System.out.println("离开代售点");
}
}
4.测试
@Test
public void test(){
ProxyTicketOffice proxyTicketOffice = new ProxyTicketOffice(new TicketOffice());
proxyTicketOffice.saleTicket(2);
//测试结果
//进入代售点
// 出售车票数 :2
// 离开代售点
}
JDK动态代理
Proxy类创建代理对象的方法
/**
* Proxy类中,创建代理对象的方法
*
* @param loader 类加载器,可以通过对象直接获取
* @param interfaces 代理类需实现的接口的列表
* @param h 调用处理器,InvocationHandler接口
* @return 调用方法的返回值
* @throws IllegalArgumentException
*/
public static Object newProxyInstance(
ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException {
return null;
}
1.定义一个接口
2.实现类
3.使用JDK中Proxy类,动态生成代理对象
代码
1.定义接口
/**
* 售票窗口
*/
public interface ITicketOffice {
/**
* 出售火车票
* @param num 出售数量
*/
void saleTicket(int num);
}
2.实现类
/**
* 售票厅
*/
public class TicketOffice implements ITicketOffice{
@Override
public void saleTicket(int num) {
System.out.println("出售车票数 :"+num);
}
}
3.测试
@Test
public void jdkProxyTest() {
//1.创建目标对象
ITicketOffice ticketOffice = new TicketOffice();
//2.创建代理对象
ITicketOffice proxyInstance = (ITicketOffice) Proxy.newProxyInstance(ticketOffice.getClass().getClassLoader(),
ticketOffice.getClass().getInterfaces(),
(proxy, method, args) -> {
System.out.println("进入代售点");
//使用反射的方式调用ticketOffice中的方法
Object invoke = method.invoke(ticketOffice, args);
System.out.println("离开代售点");
return invoke;
}
);
proxyInstance.saleTicket(1);
//测试结果
//进入代售点
// 出售车票数 :1
// 离开代售点
}
使用cglib库实现动态代理
1.导入cglib库
2.编写目标类(需要被代理的类)
3.使用cglib库中Enhancer类生成代理对象
代码
1.导入cglib库
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
2.目标类
/**
* 售票厅
*/
public class NewTicketOffice {
public void saleTicket(int num) {
System.out.println("出售车票数 :" + num);
}
}
3.测试
@Test
public void cjlibProxyTest() {
//1.创建目标对象
ITicketOffice ticketOffice = new TicketOffice();
//2.创建代理对象
ITicketOffice proxyInstance = (ITicketOffice) Enhancer.create(ticketOffice.getClass(), new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("进入代售点");
//使用反射的方式调用ticketOffice中的方法
Object invoke = method.invoke(ticketOffice, objects);
System.out.println("离开代售点");
return invoke;
}
});
proxyInstance.saleTicket(1);
//测试结果
//进入代售点
// 出售车票数 :1
// 离开代售点
}
总结
1.代理分为静态代理和动态代理,动态代理又分为JDK动态代理和cjlib动态代理
2.静态代理实现了目标对象的所有方法,一旦目标接口增加方法,代理对象和目标对象都要进行相应的修改,增加维护成本。
3.使用JDK动态代理时,目标类最少实现一个接口,使用Proxy类在内存中动态构建代理对象
4.使用cjlib动态代理时,是基于子类的动态代理,目标类不需要实现接口,但是目标类不能被final关键字修饰.