为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。代理模式有以下角色:
Java种按照代理类的生成时机不同右分为静态代理和动态代理。静态代理是编译时期就生成的。而动态代理是在Java运行过程中动态生成的。 动态代理右JDK动态代理和CGLIB动态代理两种
【案例】
如果你要买火车票,需要到火车站买票,得先坐车到火车站,排队得操作。这样比较麻烦,而火车站在多个地方都有代售点,我们去代售点买火车篇就方便很多。这个例子就是典型得代理模式,火车站是目标对象,代售点得代理对象。
【抽象角色】
public interface SellTickets{ //抽象角色
void sell(); //买票的业务功能
}
【具体角色】
public class TrainStation implements SellTickets{ //具体角色
public void sell() {System.out.println("火车站卖票");}
}
【代理角色】
public class ProxyPoint implements SellTickets{ //代理类
private TrainStation trainStation = new TrainStation();
public void sell() {
System.out.println("代售点收取服务费");
trainStation.sell();
}
}
【客户端】
public class StaticProxyTest {
public static void main(String[] args) {
ProxyPoint proxy = new ProxyPoint();
proxy.sell();
}
}
Java中提供了一个动态代理类Proxy,Proxy通过其静态方法newProxyInstance()方法创建代理对象,在java.lang.reflect包下 里面有三个关于动态代理的类
public class DynamicProxyTest {
public static void main(String[] args) {
//创建代理工厂对象
ProxyFactory factory = new ProxyFactory();
//使用factory对象的方法获取代理对象
SellTickets proxyObj = factory.getProxyObj();
proxyObj.sell();
}
}
interface SellTickets{ //抽象角色
void sell();
}
class TrainStation implements SellTickets{ //具体角色
public void sell() {System.out.println("火车站卖票");}
}
class ProxyFactory{ //代理工厂(并不是代理类)
//声明目标对象
private TrainStation trainStation = new TrainStation();
/*
newProxyInstance静态方法 创建代理对象
参数:
ClassLoader loader 类加载器,用于加载代理类。可以通过目标对象获取类加载器
Class<?>[] interfaces 目标对象实现的接口字节码对象 通过反射获取
InvocationHandler h 代理对象的调用处理程序(代理对象要完成的功能)
*/
public SellTickets getProxyObj(){ //获取代理对象
SellTickets proxyInstance = (SellTickets)Proxy.newProxyInstance(
trainStation.getClass().getClassLoader(),
trainStation.getClass().getInterfaces(),
new InvocationHandler() {
/*
Object proxy jdk创建的代理对象 和proxyInstance是同一个对象,在invoke方法中基本不用
Method method 目标类中的方法
Object[] args 调用方法的实际参数(目标方法中的参数)
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代售点收取服务费");
Object obj = method.invoke(trainStation, args); //执行目标类中的方法 也就是卖票
return obj;
}
});
return proxyInstance;
}
}
JDK动态代理需要创建抽象角色才可以使用。CGLIB是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,因为CGLIB是第三方提供的包所以需要引入jar包依赖
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
public class CGLIBDynamic {
public static void main(String[] args) {
ProxyFactory factory = new ProxyFactory();
TrainStation proxyObj = factory.getProxyObj();
proxyObj.sell();
}
}
class TrainStation{
public void sell() {System.out.println("火车站卖票");}
}
class ProxyFactory implements MethodInterceptor {
private TrainStation trainStation = new TrainStation();
public TrainStation getProxyObj(){
//创建Enhancer对象 相当于JDK动态代理中的Proxy类
Enhancer enhancer = new Enhancer();
//设置父类字节码对象
enhancer.setSuperclass(TrainStation.class);
//设置回调函数
enhancer.setCallback(this);
//创建代理对象
TrainStation trainStation = (TrainStation) enhancer.create();
return trainStation;
}
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("代售点收取手续费");
method.invoke(trainStation,objects);//调用目标对象的方法
return null;
}
}
CGLIB不能对声明final的类进行动态代理,因为CGLIB的原理是动态生成被代理的子类
1、远程代理
2、防火墙代理
3、保护代理
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/m0_60117382/article/details/123601017
内容来源于网络,如有侵权,请联系作者删除!