Java中的代理模式

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);
        }
    }
}

动态代理类
Java中的代理模式_第1张图片

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();
    }
}

总结:

  1. 动态生成代理类
  2. 通过实现接口生成代理类(目标接口必须实现接口)
  3. 代理类是实现接口的方式
  4. 调用目标类使用反射调用
  5. 目标类调用本类方法只会代理一次

CGLib动态代理

Java中的代理模式_第2张图片

目标类

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();
    }
}

总结

  1. 通过ASM第三方框架动态代理
  2. 无需接口(final修饰的类和方法除外)
  3. 代理类通过继承目标类的方式实现代理
  4. 调用目标类,使用子类调用父类的方式直接调用
  5. invokeSuper目标类中调用本类方法会再次代理
  6. incoke目标类中调用本来方法只会调用一次

你可能感兴趣的:(java,代理模式,开发语言)