代理模式,在Java中使用较多的一种模式,而Spring的AOP就是通过动态代理技术实现的。
动态代理实现的两种方式:
方式一:JDK中自带的动态代理机制,通过定义一个接口,被代理类和动态代理类实现这个接口
TargetInterface.java
/**
* 公共接口
* @author jayzh
*
*/
public interface TargetInterface {
public void targetMethodA();
public void targetMethodB(String param);
}
RealObject.java
/**
* 被代理类
* @author jayzh
*
*/
public class RealObject implements TargetInterface {
@Override
public void targetMethodA() {
System.out.println("Do something in method A.");
}
@Override
public void targetMethodB(String param) {
System.out.println("Do something in method B, Param is " + param + ".");
}
}
ProxyHandler.java
/**
* 动态代理类
* @author jayzh
*
*/
public class ProxyHandler implements InvocationHandler {
private Object delegate;
public ProxyHandler(Object delegate) {
this.delegate = delegate;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("Do something before.");
Object result = method.invoke(delegate, args);
System.out.println("Do something after.");
return result;
}
}
DynamicProxyExample.java
public class DynamicProxyExample {
public static void main(String[] args) {
// 被代理对象
RealObject obj = new RealObject();
// 动态代理类
ProxyHandler handler = new ProxyHandler(obj);
// 获取代理实例
TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(
obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),
handler);
proxy.targetMethodA();
proxy.targetMethodB("DynamicProxyExample");
}
}
运行结果
使用此种方式实现动态代理需要通过接口来实现,若某个类未实现接口则无法被代理。
方式二:使用cglib实现,通过继承某个类,在子类中拦截所有父类方法的调用并加入相关逻辑来实现动态代理
SimpleObject.java
/**
* 未实现接口的类
* @author jayzh
*
*/
public class SimpleObject {
public void hello() {
System.out.println("Hello World!");
}
public void filter() {
System.out.println("This is a filter method!");
}
public final void finalMethod() {
System.out.println("This is a final method!");
}
}
CglibProxy.java
/**
* Cglib动态代理类
* @author jayzh
*
*/
public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class<?> clazz) {
enhancer.setSuperclass(clazz);
enhancer.setCallbacks(new Callback[]{this, NoOp.INSTANCE});
enhancer.setCallbackFilter(new CallbackFilter() {
@Override
public int accept(Method method) {
if ("filter".equals(method.getName())) {
return 1;
}
return 0;
}
});
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("Do something before.");
Object result = proxy.invokeSuper(obj, args);
System.out.println("Do something after.");
return result;
}
}
CglibProxyExample.java
public class CglibProxyExample {
public static void main(String[] args) {
// 创建Cglib代理类
CglibProxy proxy = new CglibProxy();
SimpleObject obj = (SimpleObject) proxy.getProxy(SimpleObject.class);
// 普通方法
obj.hello();
// 匹配CallbackFilter的方法
obj.filter();
// final方法
obj.finalMethod();
}
}
运行结果
同时Cglib也提供了方法过滤器(CallbackFilter)来对方法进行过滤。
需要注意的是使用此种方式被final修饰的方法或类是无法被代理的。