模式定义
给某一个对象提供一个代理,并由代理对象控制对原对象的引用。
代码示例
接口,如下:
package com.bytebeats.pattern.proxy.service;
public interface HelloService {
void say(String msg);
String echo(String msg);
}
实现类
package com.bytebeats.pattern.proxy.service;
public class HelloServiceImpl implements HelloService {
@Override
public void say(String msg) {
System.out.println("hello, "+msg);
}
@Override
public String echo(String msg) {
return "echo->"+msg;
}
}
1、静态代理
静态代理类:
public class HelloServiceProxy implements HelloService {
private HelloService target;
public HelloServiceProxy(HelloService target) {
this.target = target;
}
@Override
public void say(String msg) {
target.say(msg);
}
@Override
public String echo(String msg) {
return target.echo(msg);
}
}
测试类:
public class StaticProxyDemo {
public static void main(String[] args) {
HelloService helloService = new HelloServiceImpl();
HelloService proxy = new HelloServiceProxy(helloService);
proxy.say("ricky");
System.out.println("************************");
proxy.echo("hello, world");
}
}
缺点:不够灵活
2、Jdk动态代理
使用Jdk动态代理技术生成代理,代码如下:
public class JdkProxyDemo {
public static void main(String[] args) {
new JdkProxyDemo().testProxy();
}
public void testProxy(){
HelloService helloService = getProxy(new HelloServiceImpl());
helloService.say("ricky");
System.out.println("************************");
helloService.echo("hello, world");
}
private <T> T getProxy(final Object target) {
return (T) Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
//打印日志
System.out.println("[before] The method " + methodName + " begins with " + (args!=null ? Arrays.asList(args) : "[]"));
//调用目标方法
Object result = null;
try {
//前置通知
result = method.invoke(target, args);
//返回通知, 可以访问到方法的返回值
} catch (NullPointerException e) {
e.printStackTrace();
//异常通知, 可以访问到方法出现的异常
}
//后置通知. 因为方法可以能会出异常, 所以访问不到方法的返回值
//打印日志
System.out.println("[after] The method ends with " + result);
return result;
}
});
}
}
缺点:被代理类必须实现某个接口
3、CgLib 动态代理实现
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
* CgLib动态代理实现
* @author Ricky
*
*/
public class CgLibProxyDemo {
private final Enhancer en = new Enhancer();
@Override
public <T> T getProxy(Object target) {
//进行代理
en.setSuperclass(target.getClass());
en.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
}
String methodName = method.getName();
//打印日志
System.out.println("[before] The method " + methodName + " begins with " + (args!=null ? Arrays.asList(args) : "[]"));
Object result = null;
try{
//前置通知
result = methodProxy.invokeSuper(o, args);
//返回通知, 可以访问到方法的返回值
System.out.println(String.format("after method:%s execute", method.getName()));
} catch (Exception e){
e.printStackTrace();
//异常通知, 可以访问到方法出现的异常
}
//后置通知. 因为方法可以能会出异常, 所以访问不到方法的返回值
//打印日志
System.out.println("[after] The method ends with " + result);
return result;
}
});
//生成代理实例
return (T)en.create();
}
}
4、Javassist 动态代理实现
参考我的另外一篇博文:javassist 实现动态代理