一、静态代理
- 代理模式的角色:
抽象角色:声明真实对象和代理对象的共同接口
代理角色:代理角色内部包含有真实对象的引用,从而可以操作真实对象。
真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。
package cn.wxz1997.concurrency.proxy;
/**
* @Description: 抽象角色
* @Author: wxz1997
* @Date 18-6-19下午6:43
*/
public interface ISubject {
void request();
}
package cn.wxz1997.concurrency.proxy;
/**
* @Description: 真实角色
* @Author: wxz1997
* @Date 18-6-19下午6:43
*/
public class Subject implements ISubject {
@Override
public void request() {
System.out.println("处理请求...");
}
}
package cn.wxz1997.concurrency.proxy;
/**
* @Description: 代理角色
* @Author: wxz1997
* @Date 18-6-19下午6:44
*/
public class SubjectProxy implements ISubject{
private ISubject subject;
public SubjectProxy(ISubject subject) {
this.subject = subject;
}
@Override
public void request() {
before();
this.subject.request();
after();
}
//预处理
private void before(){
//do something
System.out.println("before handle");
}
//善后处理
private void after(){
//do something
System.out.println("after handle");
}
}
package cn.wxz1997.concurrency.proxy;
/**
* @Description: 客户端代码
* @Author: wxz1997
* @Date 18-6-19下午5:17
*/
public class Client {
public static void main(String[] args) {
ISubject subject = new Subject();
ISubject subjectProxy = new SubjectProxy(subject);
subjectProxy.request();
}
}
- 在程序运行前代理类的.class文件就已经存在了。
- 静态代理的优点:客户端不需要知道实现类是什么,怎么做的,而客户端只需知道代理即可(解耦合)。
- 静态代理的缺点:①代理类和委托类实现了相同的接口,代理类通过委托类实现了相同的方法。这样就出现了大量的代码重复。②一个代理只能代理一种类型,而且是在编译器就已经确定被代理的对象。如果要代理多种类型。势必要为每一种类型都进行代理,静态代理在程序规模稍大时就无法胜任了。
二、动态代理
package cn.wxz1997.concurrency.proxy;
/**
* @Description: 抽象角色
* @Author: wxz1997
* @Date 18-6-19下午6:43
*/
public interface ISubject {
void request();
}
package cn.wxz1997.concurrency.proxy;
/**
* @Description: 真实角色
* @Author: wxz1997
* @Date 18-6-19下午6:43
*/
public class Subject implements ISubject {
@Override
public void request() {
System.out.println("处理请求...");
}
}
package cn.wxz1997.concurrency.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @Description: 创建动态代理对象
* @Author: wxz1997
* @Date 18-6-19下午7:06
*/
public class ProxyFactory {
//维护一个目标对象
private Object target;
public ProxyFactory(Object target){
this.target=target;
}
/**
* 生成代理对象
* static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )
* 第一个参数,指定当前目标对象使用类加载器,获取加载器的方法是固定的
* 第二个参数,为代理对象提供的接口是真实对象所需要实现的所有接口
* 第三个参数,执行目标对象的方法时,会触发事件处理器的invoke方法,会把当前执行目标对象的方法作为参数传入
* @return
*/
public Object getProxyInstance(){
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
//proxy表示代理,method表示原对象被调用的方法,args表示方法的参数,invoke方法返回的值是被代理接口的一个实现类。
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
//执行目标对象方法
Object value = method.invoke(target, args);
after();
return value;
}
}
);
}
//预处理
private void before(){
//do something
System.out.println("before handle");
}
//善后处理
private void after(){
//do something
System.out.println("after handle");
}
}
package cn.wxz1997.concurrency.proxy;
/**
* @Description: 动态代理测试
* @Author: wxz1997
* @Date 18-6-19下午7:12
*/
public class DynamicClient {
public static void main(String[] args) {
ISubject subject = new Subject();
ISubject proxy = (ISubject) new ProxyFactory(subject).getProxyInstance();
proxy.request();
}
}
- 代理类在程序运行时运用反射机制动态创建而成。
- 优点:动态代理是在运行时,通过反射机制实现动态代理,并且能够代理各种类型的对象。接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)。动态代理的应用使我们的类职责更加单一,复用性更强。
三、为什么要使用代理模式
代理类可以为真实角色预处理消息、过滤消息、消息转发、事后处理消息等功能。可以做到在不修改目标对象的功能前提下,对目标功能扩展。
常用于日志系统、事务、拦截器、权限控制等。这也是AOP(面向切面编程)的基本原理。AOP只是在对OOP的基础上进行进一步抽象,使我们的类的职责更加单一。
网友评论