设计模式学习-代理模式

来源:互联网 发布:软件详细说明书 编辑:程序博客网 时间:2024/04/28 18:20

代理模式是java中间件中很常用的一种模式,这篇文章是通过慕课网上的代理模式讲解的一个总结。


定义:为其他对象提供一种代理用来控制这个对象访问,起到中介作用要么去掉某些功能要么增加额外服务

分类:

  • 远程代理:不同地址空间对象,提供局域网代表对象
  • 虚拟代理:资源消耗大,或复杂对象延迟加载,真正需要时才加载
  • 保护代理:控制对象权限
  • 智能引用代理:提供目标对象额外服务(日志、权限、事务管理)

静态代理:

代理和被代理对象是确定的,实现相同接口或者继承相同抽象类,继承实现会使得代理类会无限膨胀,所以推荐用聚合

动态代理:

JDK动态代理

事务处理器InvocationHandler

动态代理类:

    • 运行时生成的类class
    • 实现一组接口interface
    • 实现动态代理类必须实现InvocationHandler接口

实现步骤:

    1. 创建类实现InvocationHandler接口中的Invoke方法
    2. 创建被代理的类及接口
    3. 调用Proxy静态方法创建代理类
      Proxy.newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHanderl h)
    4. 通过代理类调用方法

JDK动态代理只能代理实现了接口的类

CGLIB动态代理针对类实现代理,对指定目标类产生子类,通过方法拦截父类方法调用

CGLIB动态代理

实现MethodInterceptor中方法
Object intercept(Object obj, Method method, Object[] objects, MethodProxy methodProxy);

通过Proxy的newInstance返回代理对象:

  1. 声明源码,动态产生代理
    String methodString = "";for (Method m : infce.getMethods()) {    methodString += " @Override\n" +            " public void " + m.getName() + "() {\n" +            " try { " +            " Method m = " + infce.getName() + ".class.getMethod(" +"\"" + m.getName() + "\""+ ");\n" +            " h.invoke(this,m);\n" +            " }\n" +            " catch(Exception e){\n" +            " e.printStackTrace();\n" +            " }\n" +            " }\n" +            "}";}String source =                "package design.jdkproxy;\n" +                "import design.jdkproxy.InvocationHandler;\n" +                "import java.lang.reflect.Method;\n" +                "public class $Proxy0 implements " + infce.getName() + "{\n" +                " private InvocationHandler h;\n" +                "\n" +                " public $Proxy0(InvocationHandler h){\n" +                " super();\n" +                " this.h = h;\n" +                " }\n" + methodString +                "\n";String fileName = System.getProperty("user.dir") + "/src/main/java/design/jdkproxy/$Proxy0.java";File file = new File(fileName);FileUtils.writeStringToFile(file, source);


  2. 编译源码,产生代理类
    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null,null);Iterable units = fileManager.getJavaFileObjects(fileName);JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, null, null, units);task.call();fileManager.close();


  3. 将这个类load到内存,产生新的对象
    ClassLoader cl = ClassLoader.getSystemClassLoader();Class c = cl.loadClass("design.jdkproxy.$Proxy0");

  4. 返回代理对象
Constructor ct = c.getConstructor(InvocationHandler.class);return ct.newInstance(h);
0 0