Java设计模式 ---- 代理模式
一,代理模式
为其他对象提供一种代理以控制对这个对象的访问。代理模式可以分为静态代理和动态代理模式,动态代理也有通过JDK实现的动态代理模式和CGLib实现的动态代理,下面将分别展示。
二,UML图
Subject : 定义了RealSubject和Proxy的共同接口,这样可以在应用过程中通过多态实现接口公用;
RealSubject : 定义Proxy所要代理的真是实体;
Proxy : RealSubject实体的代理类,可以通过实体生成代理对象实现对实体的控制访问;
Proxy和RealSubject之间没有绝对的强一致关系,可以不需要共同实现一个接口实现多态;
三,静态代理模式
静态代理模式更多的体现在接口的调用,不多做分析,只做一个简单的展示
1,实体类
public class StaticTarget {
public void targetMethod() {
System.out.println("被代理的方法");
}
}
2,代理类
public class StaticProxy {
private StaticTarget staticTarget;
public StaticProxy(StaticTarget staticTarget) {
this.staticTarget = staticTarget;
}
public void proxyMethod() {
System.out.println("开始代理...");
staticTarget.targetMethod();
System.out.println("结束代理...");
}
}
3,客户端
public class StaticProxyTest {
public static void main(String[] args) {
StaticTarget target = new StaticTarget();
StaticProxy proxy = new StaticProxy(target);
proxy.proxyMethod();
}
}
四,动态代理_JDK实现
JDK实现的动态代理,被代理类也就是实体类必须实现一个接口,这样会与JDK生成的虚拟代理类存在强一致性关系,从而形成多态调用。
1,顶层接口
public interface ProxyInterface {
public void targetMethod();
}
2,实体类 — 实现顶层接口
public class JDKProxyTarget implements ProxyInterface{
@Override
public void targetMethod() {
System.out.println("代理方法...");
}
}
3,代理对象生成
该类只负责生成代理对象,具体代理对象的方法调用。JDK在生成代理对象时,也会生成一个该代理对象所属的.class文件。所return的接口对象实际数据该代理类的对象,通过多态调用,所调用的方法为该虚拟类内部的方法,这一块内容将在手写JDK动态代理中分析;
public class JDKProxy {
private ProxyInterface proxyInterface;
public JDKProxy(ProxyInterface proxyInterface) {
this.proxyInterface = proxyInterface;
}
public Object instanceProxy() {
System.out.println("代理方法开始...");
ProxyInterface instance = (ProxyInterface) Proxy.newProxyInstance(
proxyInterface.getClass().getClassLoader(),
proxyInterface.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
method.invoke(proxyInterface, args);
System.out.println("代理方法结束...");
return null;
}
});
return instance;
}
}
\* 该代理对象生成类会先获取实体类的引用,通过该实体类来生成对应的代理类和代理对象;
\* 在newInstance()(自定义方法)方法中,通过调用JDK所提供的Proxy对象来获取代理对象;
* 在JDK提供的newProxyInstance()中,需要依次传入实体对象的类加载器,类实现的所有接口和InvocationHandler的实现类对象,这里通过匿名内部类获取;
\* InvocationHandler的实现类会重写该接口的invoke()方法,也是整个动态代理最终执行方法的位置,method就是客户端所执行的方法,通过反射方式执行;
4,客户端
public class JDKProxyTest {
public static void main(String[] args) {
JDKProxy proxy = new JDKProxy(new JDKProxyTarget());
ProxyInterface proxyInterface = (ProxyInterface) proxy.instanceProxy();
System.out.println(proxyInterface.getClass());
proxyInterface.targetMethod();
}
}
5,执行接口
从控制台结果中可以看出,所生成的proxyInterface对象,并不属性原来的实体类,而是JDK自动生成的$Proxy0类。
五,动态代理_CGLib方式
与JDK代理模式在结构上不同的是 :
\* 实体类不需要继承或者实现任何类和接口,不存在强一致性关系
\* 代理类必须实现MethodInterceptor接口并实现interceptor()方法,
1,实体类
public class CglibTarget {
public void targetMethod() {
System.out.println("代理方法...");
}
}
2,代理类
public class CglibProxy implements MethodInterceptor{
public Object instanceProcy(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 {
System.out.println("代理前...");
Object result = methodProxy.invokeSuper(o, objects);
System.out.println("代理后...");
return result;
}
}
\* 该代理类,在instanceProcy()方法中,通过Enhancer创建出目标类的代理对象;
\* 在实现的intercept()方法中,通过反射进行完成调用;
3,客户端
public class CglibProxyTest {
public static void main(String[] args) {
CglibProxy cglibProxy = new CglibProxy();
CglibTarget proxy = (CglibTarget)cglibProxy.instanceProcy(CglibTarget.class);
proxy.targetMethod();
}
}
还没有评论,来说两句吧...