定义:
给某一个对象提供一个代理,并由代理对象控制对原对象的引用。
1. 静态代理
静态代理在使用时,需要定义接口和父类,被代理对象与代理对象一起是实现相同的接口或者是继承相同的父类。
/**
* 接口
*/
public interface IUserDao {
void save();
}
/**
* 接口实现
* 目标对象
*/
public class UserDao implements IUserDao {
public void save() {
System.out.println("----已经保存数据!----");
}
}
/**
* 代理对象,静态代理
*/
public class UserDaoProxy implements IUserDao{
//接收保存目标对象
private IUserDao target;
public UserDaoProxy(IUserDao target){
this.target=target;
}
public void save() {
System.out.println("开始事务...");
target.save();//执行目标对象的方法
System.out.println("提交事务...");
}
}
/**
* 测试类
*/
public class App {
public static void main(String[] args) {
//目标对象
UserDao target = new UserDao();
//代理对象,把目标对象传给代理对象,建立代理关系
UserDaoProxy proxy = new UserDaoProxy(target);
proxy.save();//执行的是代理的方法
}
}
可以做到在不修改目标对象的功能前提下,对目标功能扩展.
缺点
因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象都要维护.
2. 动态代理
定义:
动态代理具有更强的灵活性,因为它不用在我们设计实现的时候就指定某一个代理类来代理哪一个被代理对象,我们可以把这种指定延迟到程序运行时由JVM来实现。代理类并不需要在Java代码中定义,而是在运行时动态生成的。
- 创建一个实现InvocationHandler接口的类,它必须实现invoke()方法
- 创建被代理的类及接口
- 调用Proxy的静态方法,创建一个代理类
- 通过代理调用方法
2.1 两种写法
public interface ICoder {
public void implDemands(String demandName);
}
public class CoderDynamicProxy implements InvocationHandler{
//被代理的实例
private ICoder coder;
public CoderDynamicProxy(ICoder _coder){
this.coder = _coder;
}
//调用被代理的方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(System.currentTimeMillis());
Object result = method.invoke(coder, args);
System.out.println(System.currentTimeMillis());
return result;
}
}
public class DynamicClient {
public static void main(String args[]){
//要代理的真实对象
ICoder coder = new JavaCoder("Zhang");
//创建中介类实例
InvocationHandler handler = new CoderDynamicProxy(coder);
//获取类加载器
ClassLoader cl = coder.getClass().getClassLoader();
//动态产生一个代理类
ICoder proxy = (ICoder) Proxy.newProxyInstance(cl, coder.getClass().getInterfaces(), handler);
//通过代理类,执行doSomething方法;
proxy.implDemands("Modify user management");
2.2 JDK生成代理对象的API
在实现newProxyInstance方法,接收三个参数:
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )
ClassLoader loader
,:指定当前目标对象使用类加载器,获取加载器的方法是固定的Class<?>[] interfaces
,:目标对象实现的接口的类型,使用泛型方式确认类型InvocationHandler h
:事件处理,执行目标对象的方法时,会触发事件处理器的方法,会把当前执行目标对象的方法作为参数传入
参考:
Java的代理模式