考虑这样一个场景:
假如你需要扩展某个方法的功能, 例如在调用该方法前打印日志,直接修改原方法是一个方案,但是以后又要求把打印功能去掉呢?。本着"对修改封闭,对扩展开放"的原则",可以考虑使用动态代理。下面的例子展示了如何使用动态代理。
—>详细原理到这个链接
JDK动态代理
首先,构造一个简单的JDK动态代理类需要以下元素:
1.接口
2.接口实现类
3.InvocationHandler实现类
4.通过Proxy.newProxyInstance方法生成代理类对象
JDK动态代理只能针对实现了接口的类进行代理
例子
// 接口
public interface Star {
void sing();
void dance();
}
// 接口实现类
public class StarImpl implements Star{
@Override
public void dance(){
System.out.println("He is dancing.");
}
@Override
public void sing(){
System.out.println("he is singing.");
}
}
// InvocationHandler实现类
public class StarInvocationHandler implements InvocationHandler{
//代理的目标对象
private Object target;
public StarInvocationHandler(Object target){
this.target = target;
}
@Override
//proxy 调用方法的代理实例
public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
// 增强的方法
if(method.getName().equals("sing"))
{
System.out.println("唱歌之前的热身");
}
if(method.getName().equals("dance"))
{
System.out.println("跳舞之前的热身");
}
// 将请求转发给目标对象
return method.invoke(target, args);
}
}
\\ 测试
Star star = new StarImpl();
Star starProxy = (Star)Proxy.newProxyInstance(star.getClass().getClassLoader(),
star.getClass().getInterfaces(),
new StarInvocationHandler(star));
starProxy.dance();
运行结果:
跳舞之前的热身
He is dancing.
让我们看看Proxy的构造动态代理对象的方法:
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
前两个参数是基于被代理对象调用的,因此,InvocationHandler 的实现将定义我们的额外操作。
动态代理的工作模式就是:将增强的方法实现交给InvocationHandler, 当外界对Proxy角色的每一个方法调用, Proxy都会交给InvocationHandler来处理, 而InvocationHandler则调用具体的对象(realObject)的方法.
Proxy——> InvocationHandler——>realObject
CGLib动态代理
首先,构造一个简单的CGLib动态代理类需要以下元素:
1.代理的目标类
2.MethodInterceptor实现类
3.使用Enhancer 类生成代理类对象
CGLib动态代理适用于没有实现接口的类进行代理
例子
// 目标类
public class StarAct {
public void act(){
System.out.println("The star is acting");
}
}
// 实现方法拦截器
public class StartIntercepter implements MethodInterceptor {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable{
System.out.println("演出时要拦截观众.");
methodProxy.invokeSuper(o, objects);
return o;
}
}
// 测试类
public class proxyTest {
public static void main(String[] args) {
// 使用CGLib做动态代理
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(StarAct.class);
enhancer.setCallback(new StartIntercepter());
StarAct starAct = (StarAct)enhancer.create();
starAct.act();
}
}
// 运行结果:
演出时要拦截观众.
The star is acting