Java中的代理模式
- 1. 静态代理
- JDK动态代理
- CGLib动态代理
1. 静态代理
接口
public interface ICeo {
void meeting(String name) throws InterruptedException;
}
目标类
public class Ceo implements ICeo{
public void meeting(String name) throws InterruptedException {
Thread.sleep(2000);
System.out.println("和"+name+"谈成了34亿的项目");
}
}
代理类
public class CeoProxy implements ICeo{
private Ceo ceo;
public CeoProxy(Ceo ceo) {
this.ceo = ceo;
}
@Override
public void meeting(String name) throws InterruptedException {
System.out.println("秘书登记来访: "+name);
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ceo.meeting(name);
stopWatch.stop();
double totalTimeMillis = stopWatch.getTotalTimeSeconds();
System.out.println("耗时: "+totalTimeMillis);
}
}
测试
public class CeoTest {
public static void main(String[] args) throws InterruptedException {
Ceo ceo = new Ceo();
CeoProxy ceoProxy = new CeoProxy(ceo);
ceoProxy.meeting("XXX");
}
}
JDK动态代理
接口
public interface IDao {
void select();
}
目标类
public class UserDao implements IDao{
@Override
public void select() {
try {
Thread.sleep(2000);
System.out.println("select ----");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
动态代理类
public class JdkProxy implements InvocationHandler {
private Object target;
public JdkProxy(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
StopWatch stopWatch = new StopWatch();
System.out.println("前置方法");
stopWatch.start();
Object obj = method.invoke(target, args);
stopWatch.stop();
System.out.println("后置方法");
System.out.println("耗时: "+stopWatch.getTotalTimeSeconds());
return obj;
}
}
测试
public class DaoTest {
public static void main(String[] args) {
UserDao userDao = new UserDao();
IDao dao = (IDao) Proxy.newProxyInstance(UserDao.class.getClassLoader(), UserDao.class.getInterfaces(), new JdkProxy(new UserDao()));
dao.select();
}
}
总结:
- 动态生成代理类
- 通过实现接口生成代理类(目标接口必须实现接口)
- 代理类是实现接口的方式
- 调用目标类使用反射调用
- 目标类调用本类方法只会代理一次
CGLib动态代理
目标类
public class ZlmDao {
public void select(){
try {
Thread.sleep(2000);
System.out.println("select ---");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
代理类
public class CglibProxy implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
System.out.println("前置增强");
Object result = proxy.invokeSuper(obj, args);
stopWatch.stop();
System.out.println("后置增强");
System.out.println("耗时: "+stopWatch.getTotalTimeSeconds());
return result;
}
}
测试
public class ZlmDaoTest {
public static void main(String[] args) {
//实例化增强器
Enhancer enhancer = new Enhancer();
//设置需要代理的目标类
enhancer.setSuperclass(ZlmDao.class);
//设置拦截对象回调的实现类
enhancer.setCallback(new CglibProxy());
//生成代理类
ZlmDao zlmDao = (ZlmDao) enhancer.create();
zlmDao.select();
}
}
总结
- 通过ASM第三方框架动态代理
- 无需接口(final修饰的类和方法除外)
- 代理类通过继承目标类的方式实现代理
- 调用目标类,使用子类调用父类的方式直接调用
- invokeSuper目标类中调用本类方法会再次代理
- incoke目标类中调用本来方法只会调用一次