动态代理的用途:
动态代理的用途与装饰模式很相似,就是为了对某个对象进行增强。所有使用装饰者模式的案例都可以使用动态代理来替换,动态代理可以更好的解耦合
增强有3个手段
1. 继承
被增强对象不能变
增强内容不能变
2. 装饰者模式
被增强对象可变
但增强内容不能变
3. 动态代理
被增强对象可变
增强内容也可变
如何实现动态代理?
定义一个接口Interface, 被增强的对象的类都会实现这个接口
public interface Interface {
public void fun();
}
实现这个Interface接口:
而这个InterfaceImpl就是动态代理中被增强的内容
public class InterfaceImpl implements Interface {
@Override
public void fun() {
System.out.println("目标方法调用");
}
}
定义一个接口Advice, 增强内容的类都会实现这个接口
这个接口有两个未实现的方法:
before()前置增强的方法
after()后置增强的方法
public interface Advice {
public void before();
public void after();
}
而实现了Advice接口的对象就是动态代理中增强内容
JavaAPI:
java.lang.reflect.Proxy
Object proxyObject = Proxy.newProxyInstance(ClassLoader classLoader, Class[] interfaces, InvocationHandler h);
返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序
参数:
classLoader - 定义代理类的类加载器
interfaces - 代理类要实现的接口列表
h - 指派方法调用的调用处理程序
返回:
一个带有代理类的指定调用处理程序的代理实例,它由指定的类加载器定义,并实现指定的接口
java.lang.reflect.InvocationHandler
public Object invoke(Object proxy, Method method, Object[] args);
这个invoke()方法在调用代理对象所实现接口中的方法时调用
* Object proxy:当前对象,即代理对象!在调用谁的方法!
* Method method:当前被调用的方法(目标方法)
* Object[] args:目标方法参数
调用proxy实例的方法时, 都会被InvocationHandler所捕获, 因此只要实现InvocationHandler实现类的invoke()方法, 就可以实现目标方法的增强
定义一个类ProxyFactory
该类通过两个参数的public ProxyFactory(target,advice)构造方法构造ProxyFactory实例, 然后通过该实例的getProxy()方法得到代理对象
public class ProxyFactory {
private Object target; // 目标对象
private Advice advice; // 增强对象
public ProxyFactory(Object target, Advice advice) {
this.target = target;
this.advice = advice;
}
/**
* 得到代理对象
*/
public Object getProxy() {
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 执行前置增强
advice.before();
// 执行目标对象的目标方法, 用result接收返回值
Object result = method.invoke(target, args);
// 执行后置增强
advice.after();
// 返回目标方法的返回值result
return result;
}
});
}
}
测试动态代理
public static void main(String[] args) {
InterfaceImpl target = new InterfaceImpl();
// 实现一个Advice的实例对象, 这个对象就是动态代理中增强内容
Advice advice = new Advice() {
@Override
public void before() {
System.out.println("目标方法调用之前, 执行前置增强");
}
@Override
public void after() {
System.out.println("目标方法调用之后, 执行后置增强");
}
};
ProxyFactory proxyFactory = new ProxyFactory(target, advice);
Interface proxy = (Interface) proxyFactory.getProxy();
proxy.fun();
}
Console输出:
方法调用之前, 执行前置增强
目标方法调用
方法调用之后, 执行后置增强
来源:oschina
链接:https://my.oschina.net/u/2503731/blog/659708