静态代理
静态代理:
为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
设计思路:定义一个抽象角色,让代理角色和真实角色分别去实现它。
1.抽象角色:声明真实对象和代理对象的共同接口。
2.真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。它只关注真正的业务逻辑。
3.代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
静态代理实现:
package HeadFirstDesignMode.proxy;
/**
* 描述:代理模式-静态代理
*/
public class StaticProxyPattern {
public static void main(String[] args) {
Station trainStation = new TrainStationImpl("xxx车站");
// 客户端直接操作代理类,避免了客户端与真实类的直接交涉
Station station = new StationProxy(trainStation);
station.sellTickets();
station.transport();
}
}
// 抽象角色-车站接口
interface Station {
void sellTickets();//卖票
void transport();//运输
}
// 真实角色-车站接口实现类
class TrainStationImpl implements Station {
private String name;
public TrainStationImpl(String name) {
this.name = name;
}
@Override
public void sellTickets() {
System.out.println(name + "卖票。。。");
}
@Override
public void transport() {
System.out.println(name + "运输乘客。。。");
}
}
// 代理角色-作为火车站的一个代理类供客户端调用
class StationProxy implements Station {
Station station;
public StationProxy(Station station) {
this.station = station;
}
@Override
public void sellTickets() {
station.sellTickets();//代理类中调用真实角色的方法
}
public void otherOperate() {
System.out.println("代理类的额外操作。。。");
}
@Override
public void transport() {
// 车站代理不能运输,调用真实角色进行运输
station.transport();
}
}
动态代理
静态代理模式中,真实角色必须是事先已经存在的,并将其作为代理对象的内部属性,并且真实角色必须对应一个代理角色,如果大量使用会导致类的急剧膨胀。那么,如果事先并不知道真实角色,该如何使用代理呢?
这个问题可以通过Java的动态代理类来解决。动态代理必需用到以下两个类。
**(1).Interface InvocationHandler:**该接口中仅定义了一个方法Object invoke(Object obj, Method method, Object[] args)用于完成真实角色中方法的调用。
**(2).Proxy:**该类即为动态代理类,作用类似于静态代理模式的代理类
动态代理实现:
package HeadFirstDesignMode.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 描述:代理模式-动态代理
*/
public class DynamicProxyPattern {
public static void main(String[] args) {
Station stationImpl = new TrainStationImpl("杭州东站");//将要被代理的真实对象
/**
* 动态代理就好处在这里,不管这里是要代理什么对象,I
* nvocationHandlerImpl与Proxy中代码都不必改变,
* 都是用下面同样的方式去产生代理对象
*/
InvocationHandler handler = new InvocationHandlerImpl(stationImpl);
//用InvocationHandler的实现类包装真实的被代理角色
ClassLoader loader = handler.getClass().getClassLoader();
//获取当前java程序的类装载器Classloader
Class[] interfaces = stationImpl.getClass().getInterfaces();
//获取被代理角色实现的所有接口
/**
* Proxy类是动态代理模式涉及到的另一个重要的类,该类即为动态代理类,作用类似于静态代理模式中的代理类StationProxy,
* 它有一个重要方法newProxyInstance(ClassLoader loader, Class[] interfaces,InvocationHandler handler): * 返回代理类的一个实例。
* 其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组,handler是调用处理器InvocationHandler。
* 传递此参数以使产生的代理对象可以当做真实类任意实现接口的子类来用。
*/
Station station = (Station) Proxy.newProxyInstance(loader, interfaces, handler);
station.sellTickets();//将会去执行DynamicProxy的invoke方法,完成对目标对象方法的调用
station.transport();
}
}
class InvocationHandlerImpl implements InvocationHandler {
Object proxyobj;
public InvocationHandlerImpl(Object object) {
this.proxyobj = object;
}
@Override
public Object invoke(Object obj, Method method, Object[] args)
throws Throwable {
System.out.println("start doing .........");
method.invoke(proxyobj, args);//调用被代理对象proxyobj的方法method,传入一个参数组args
System.out.println("stop doing .........");
return null;
}
}
cglib代理
我们知道Java中有一个动态代理(Proxy)也是做这个事情的,那我们为什么不直接使用Java动态代理,而要使用CGLIB呢?答案是CGLIB相比于JDK动态代理更加强大,JDK动态代理虽然简单易用,但是其有一个致命缺陷是,只能对接口进行代理。如果要代理的类为一个普通类、没有接口,那么Java动态代理就没法使用了。
Enhancer
Enhancer可能是CGLIB中最常用的一个类,和Java1.3动态代理中引入的Proxy类差不多。和Proxy不同的是,Enhancer既能够代理普通的class,也能够代理接口。Enhancer创建一个被代理对象的子类并且拦截所有的方法调用(包括从Object中继承的toString和hashCode方法)。Enhancer不能够拦截final方法,例如Object.getClass()方法,这是由于Java final方法语义决定的。基于同样的道理,Enhancer也不能对fianl类进行代理操作。这也是Hibernate为什么不能持久化final class的原因。
实现如下:
package HeadFirstDesignMode.proxy;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* 描述:cglib代理模式
*/
public class CglibDemo implements MethodInterceptor {
public Object getTarget() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(CglibTest.class);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
return methodProxy.invokeSuper(o, objects);
}
public static void main(String[] args) {
CglibTest target = (CglibTest) new CglibDemo().getTarget();
System.out.println(target.hello());
}
}
class CglibTest {
public String hello() {
System.out.println("execute hello method");
return "hello cglib";
}
}
标签:Station,角色,Object,代理,模式,station,public
From: https://blog.51cto.com/u_11906056/7011752