java高新技术-代理

程序中代理的概念与作用

  要为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能,例如,异常处理、日志、计算方法的运行时间、事务管理、等等。

  代理架构图:

  

  如果采用工厂模式和配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中配置是使用目标类,还是使用代理类,

  这样以后很容易切换,例如:想要日志功能时就配置代理类,否则配置目标类,这样,增加系统功能很容易。

1.分析代理类的作用与原理及AOP概念

  代理是实现AOP功能的核心和关键技术。

  系统中存在交叉业务,一个交叉业务就是要切入到系统中的一个方面。

  安全,事务,日志等功能要贯穿到好多个模块中,所以,他们就是交叉业务

  用具体的程序代码描述交叉业务:

  

  交叉业务的编程问题即为面向方面的变成(Aspect oriented program,简称AOP,AOP的目标就是要使交叉业务模块化。可以采用将切面代码移动到原始方法的周围。)

2.动态代理技术

  > JVM可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作代理类,即动态代理类。

  > JVM生成的动态类必须实现一个或多个接口,所以,JVM生成的动态类只能用作具有相同接口的目标类的代理.

  *如果目标类没有实现接口,要想生成代理使用 CGLIB

  > CGLIB 库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现接口的的类生成动态代理类,那么可以使用CGLIB库。

  > 代理类的各个方法中通常除了要调用目标的相应方法和对外返回目标返回的结果外,还可以在代理方法中的如下四个位置加上系统功能代码:

    > 1.在调用目标方法之前

    > 2.在调用目标方法之后

    > 3.在调用目标方法前后

    > 4.在处理目标方法异常的catch块中

    

void sayHello(){
       ..............

       try{
             target.sayHello();
       }catch(Exception e){
                 ...............
       }
       .................
}

  

创建动态类及查看其方法列表信息

  分析JVM动态生成的类

    创建实现了Collection接口的动态类和查看其名称,分析Proxy.getProxyClass方法的各个参数。

    编码列出动态类中的所有构造方法和参数签名

    编码列出动态类中的所有方法和签名

    创建动态类的实例对象

      > 用反射获得构造方法

      > 编写一个最简单的InvocationHandler

      > 调用构造方法创建动态类的实例对象,并将编写的InvocationHandler类的实例对象传进去

      > 打印创建的对象和调用对象的没有返回值得方法和getClass方法,调用其他有返回值的方法会抛异常。

  

public class ProxyTest {
    public static void main(String[] args) {
       // 1.先创建动态类 ,在创建实例对象     Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
        System.out.println(clazzProxy1.getName());

        System.out.println("-----------begin constructors list");
        /*$Proxy0()
        $Proxy0(InvocationHandler,int)*/
        Constructor[] constructors = clazzProxy1.getConstructors(); //返回所有的构造方法
        for(Constructor constructor: constructors){
            String name = constructor.getName();
            StringBuilder sBuilder = new StringBuilder(name);
            sBuilder.append("(");
            Class[] clazzParams = constructor.getParameterTypes();//返回所有的参数列表类型
            for(Class clazzParam : clazzParams){
                sBuilder.append(clazzParam.getName()).append(",");
            }
            if(clazzParams!= null && clazzParams.length != 0){
                sBuilder.deleteCharAt(clazzParams.length-1);  //去掉最后一个 ,
            }
            sBuilder.append(")");
            System.out.println(sBuilder.toString());
        }

        System.out.println("-----------begin methods list");
        /*$Proxy0()
        $Proxy0(InvocationHandler,int)*/
        Method[] methods = clazzProxy1.getMethods(); //返回所有的方法
        for(Method method: methods){
            String name = method.getName();
            StringBuilder sBuilder = new StringBuilder(name);
            sBuilder.append("(");
            Class[] clazzParams = method.getParameterTypes();//返回所有的参数列表类型
            for(Class clazzParam : clazzParams){
                sBuilder.append(clazzParam.getName()).append(",");
            }
            if(clazzParams!= null && clazzParams.length != 0){
                sBuilder.deleteCharAt(sBuilder.length()-1);  //去掉最后一个 ,
            }
            sBuilder.append(")");
            System.out.println(sBuilder.toString());
        }

    }
}

  

    > InvocationHandler 对象的内部功能

Constructor constructor = clazzProxy1
                .getConstructor(InvocationHandler.class);
        class MyInvocationHander1 implements InvocationHandler {

            @Override
            public Object invoke(Object proxy, Method method, Object[] args)
                    throws Throwable {
                // TODO Auto-generated method stub
                return null;
            }

        }
        Collection proxy1 = (Collection) constructor
                .newInstance(new MyInvocationHander1());
        System.out.println(proxy1); // 这里返回为null 是因为proxy1.toString()为null

        proxy1.clear();
        // proxy1.size(); //由于有返回值,会抛异常

        Collection proxy2 = (Collection) constructor
                .newInstance(new InvocationHandler() {

                    @Override
                    public Object invoke(Object proxy, Method method,
                            Object[] args) throws Throwable {
                        // TODO Auto-generated method stub
                        return null;
                    }
                });
        // 2.在创建动态类时直接实例化对象
        Collection proxy3 = (Collection) Proxy.newProxyInstance(
                Collection.class.getClassLoader(),
                new Class[] { Collection.class }, new InvocationHandler() {
                    ArrayList target = new ArrayList<>();

                    @Override
                    public Object invoke(Object proxy, Method method,
                            Object[] args) throws Throwable {
                        long startTime = System.currentTimeMillis();
                        Object object = method.invoke(target, args);
                        long endTime = System.currentTimeMillis();
                        System.out.println(method.getName()
                                + " running time of " + (endTime - startTime));
                        return object;
                    }
                });
        proxy3.add("zxx");
        proxy3.add("lhm");
        proxy3.add("bxd");
        System.out.println(proxy3.size());

      /**
       * $proxy0 为什么返回的不是ArrayList而是一个代理
       * 因为getClass()是从Object上继承的,Object中只有三个方法时交给handler处理的 hashCode,equals,toString
        * 所以调用getClass()时,返回的是自己实现的
       */
      System.out.println(proxy3.getClass().getName());

 

 

  > InvocationHandler 对象的运行原理

    Client程序调用objProxy.add("abc")方法时,涉及三个要素:objProxy对象、add方法、"abc"参数

    Class Proxy${

      add(Object object){

        return handler.invoke(Object proxy, Method method, Object[] args);

      }

    }

    

   > 面向切面编程:

    把切面的代码,以对象的形式进行封装,以对象的形式传递给你,你只要执行这个对象,就等于执行了切面的代码

  

  > 编写可生成代理和插入通告的通用方法

    

Collection proxy3 = (Collection)getProxy(new ArrayList<>(),new MyAdvice());
        //每调用一次,都会调用 一次InvocationHandler 的 invoke方法
        proxy3.add("zxx");
        proxy3.add("lhm");
        proxy3.add("bxd");
        System.out.println(proxy3.size());

  

getProxy方法
private static Object getProxy(final Object target, final MyAdvice advice) {
        Object proxy3 =  Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), new InvocationHandler() {

                    @Override
                    public Object invoke(Object proxy, Method method,
                            Object[] args) throws Throwable {
                        advice.beforeMethod(method);
                        Object object = method.invoke(target, args);
                        advice.afterMethod(method);
                        return object;
                    }
                });
        return proxy3;
    }
 

MyAdvice类:

public class MyAdvice implements Advice {

    long startTime = 0;
    @Override
    public void beforeMethod(Method method) {
        startTime = System.currentTimeMillis();

    }

    @Override
    public void afterMethod(Method method) {
        long endTime = System.currentTimeMillis();
        System.out.println(method.getName()
                + " running time of " + (endTime - startTime));
    }

}

  目的是把 代理 和系统功能都转义成了外边的 对象

  完成Spring 只完成一件事:写MyAdvice, target是在配置文件中配置的

时间: 2024-10-11 22:37:10

java高新技术-代理的相关文章

黑马程序员——Java高新技术代理

代理 普通代理 很多时候,我们使用别人代码往往会发现别人代码的功能并不是十分符合我们的需求,调用别人的方法的时候,总是先new一个对象,然后我们的前处理做完,然后调用别人代码的方法,再加入后处理,这样做往往十分麻烦.代理就为其他类提供了一种控制其对象的方法.代理类和委托类必须实现同一个接口,这样代理类才能在需要的时候代替委托类对象,执行委托类的方法. interface Solution{ public void doSomething(); } //委托类Demo实现了接口 class Dem

理解java动态代理

java动态代理是java语言的一项高级特性.在平时的项目开发中,可能很难遇到动态代理的案例.但是动态代理在很多框架中起着不可替代的作用,例如Spring的AOP.今天我们就聊一聊java动态代理的实现原理. jdk对于动态代理的支持主要依赖于两个类:Proxy和InvocationHandler.我们先看一下类图. Subject类是主题类,定义了我要做什么.我们需要代理的类即实现Subject接口的RealSubject. 1.InvocationHandler InvocationHand

java动态代理的实现

动态代理作为代理模式的一种扩展形式,广泛应用于框架(尤其是基于AOP的框架)的设计与开发,本文将通过实例来讲解Java动态代理的实现过程. 友情提示:本文略有难度,读者需具备代理模式相关基础知识,. 通常情况下,代理模式中的每一个代理类在编译之后都会生成一个class文件,代理类所实现的接口和所代理的方法都被固定,这种代理被称之为静态代理(Static Proxy).那么有没有一种机制能够让系统在运行时动态创建代理类?答案就是本文将要介绍的动态代理(Dynamic Proxy).动态代理是一种较

java的代理和动态代理简单测试

什么叫代理与动态代理? 1.以买火车票多的生活实例说明. 因为天天调bug所以我没有时间去火车票,然后就给火车票代理商打电话订票,然后代理商就去火车站给我买票.就这么理解,需要我做的事情,代理商帮我办了,但是需要出手续费. 废话不说了,直接上java代码吧! java动态代理 //接口   (抽象买票的事情) public interface ICalc {     public int add(int i, int j);}//实现这个接口   (具体到我买票的事情) public class

java动态代理机制

首先了解代理设计模式,其思想是为其他对象提供一种代理以控制对这个对象的访问. java动态代理就是遵循这种思想,spring中的AOP实现原理就是java的动态代理. 在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface).另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的. 每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通

java动态代理

要想了解Java动态代理,首先要了解什么叫做代理,熟悉设计模式的朋友一定知道在Gof总结的23种设计模式中,有一种叫做代理(Proxy)的对象结构型模式,动态代理中的代理,指的就是这种设计模式. 在我看来所谓的代理模式,和23种设计模式中的"装饰模式"是一个东西.23种设计模式中将它们作为两种模式,网上也有些文章讲这两种模式的异同,从细节来看,确实可以人为地区分这两种模式,但是抽象到一定高度后,我认为这两种模式是完全一样的.因此学会了代理模式,也就同时掌握了装饰模式. 代理模式 代理模

java 动态代理示例,带主要注释

Java proxy是基于反射,仅仅支持基于接口的动态代理. java 动态代理是一切架构的基础,必须了解. 废话少说,先上代码获得感性认识. 示例代码有主要注释. 接口: public interface Subject { String hello(String name); void say();} 接口实现: public class ImpSubject implements Subject { @Override public String hello(String name){ r

java动态代理原理及解析

代理:设计模式 代理模式是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个真实对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理. 通过代理层这一中间层,有效的控制对于真实委托类对象的直接访问,同时可以实现自定义的控制策略(Spring的AOP机制),设计上获得更大的灵活性. java动态代理的类和接口(jdk1.6源码) 1,java.lang.reflect.Proxy:动态代理机制的主类,提供一组静态方法为一组接口动态的生成对

彻底理解JAVA动态代理

注:本文转自 http://www.cnblogs.com/flyoung2008/archive/2013/08/11/3251148.html 代理设计模式 定义:为其他对象提供一种代理以控制对这个对象的访问. 代理模式的结构如下图所示. 动态代理使用 java动态代理机制以巧妙的方式实现了代理模式的设计理念. 代理模式示例代码 public interface Subject { public void doSomething(); } public class RealSubject i