Java-动态代理技术

1.程序中的代理

为具有相同接口的目标类的各个方法,添加一些系统功能,如日志,异常处理,计算方法运行的

时间,事务管理等等,都可以交给另一个类去实现这些功能,该类称为代理类。

注意:为了让代理类共享目标类中的各个方法,可以让代理类实现和目标类相同的接口。

  public class AProxy {
    //AProxy类为A的代理类,可以计算sayHi方法的运行时间
    public  void getTime()
    {
        //方法开始前时间
         new A().sayHi();
        //方法结束后时间
    }
}
class A
{
    void sayHi()
    {
        System.out.println("hi,everyone!");
    }
}

2.代理架构图

它采用工厂模式和配置文件的方式进行管理,这样就不需要修改客户端程序,通过

配置文件指定使用目标类,还是代理类。这样做添加/去掉系统功能变得简单。

当我们需要测试系统的性能时,可以使用代理类,客户要使用时可以使用目标类

3.AOP(Aspect oriented program)

交叉业务:要处理不同层面的业务(service),称为交叉业务,如安全,事务,日志等。

安全       事务         日志
    StudentService  ------|----------|------------|-------------
    CourseService   ------|----------|------------|-------------
    MiscService       ------|----------|------------|-------------

用具体的程序代码描述交叉业务:
     method1         method2          method3
     {                      {                       {
       ------------------------------------------------------切面
          ....            ....              ......
       ------------------------------------------------------切面
      }                       }                       }

面向方面的编程(简称AOP),AOP的目标就是要使交叉业务模块化。

可以采用将切面代码移动到原始方法的周围,这与直接在方法中编写切面代码的运行效果是一样的,如下所示:
       ------------------------------------------------------切面
       func1         func2            func3
        {             {                {
          ....            ....              ......
         }             }                }
      ------------------------------------------------------切面

这里就是使用代理技术解决这种问题,代理是实现AOP功能的核心和关键技术。
4.动态代理技术

  • 要为系统中的各种接口的类增加代理功能,那将需要太多的代理类,全部采用静态代理方式,将是一件非常麻烦的事情!
  • JVM提供了动态代理类(Proxy)。即可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作代理类。这里是仅指具有接口的代理类和目标类。
  • 对于没有接口的目标类,CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现接口的类生成动态代理类,那么可以使用CGLIB库。

代理方法中的有如下四个位置加上系统功能代码:

1.在调用目标方法之前
     2.在调用目标方法之后
     3.在调用目标方法前后
     4.在处理目标方法异常的catch块中

class proxy{
    void sayHello(){
        ………//1
        try{
            target.sayHello();
        }catch(Exception e){
            ………//4
        }
        …………//2
    }
}

5.Proxy(代理类)

      |-java.lang.reflect.Proxy

Proxy提供了创建动态代理类和实例的静态方法,它也是这些创建出来类的超(父)类。

构造方法:

protected  Proxy(InvocationHandler  h);//使用其调用处理程序的指定值从子类(通常为动态代理类)构建新的 Proxy 实例

成员方法:

static Class<?> getProxyClass(ClassLoader loader,Class<?> interfaces);//创建一个具有接口的动态代理类。

static Object newProxyInstance (ClassLoader loader,Class<?>[] interfaces,InvocationHandler h);//返回一个代理类实例对象

创建代理类及其实例对象:

法一:先创建代理类,再用代理类的构造方法创建实例对象

public static void main(String[] args) {
        // 获得一个集合接口的代理类,为其指定接口和类加载器
        //通常loader,interface是一样的字节码产生的
        Class  clazzProxy1=Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
        System.out.println(clazzProxy1.getName());
        //创建一个代理类实例
        //注意:clazzProxy1.newInstance()调用的是它的无参构造方法创建实例,但是它没有无参的构造方法
        //通过有参构造方法创建实例
        Constructor ct=clazzProxy1.getConstructor(InvocationHandler.class);
        class MyinvocationHandler implements InvocationHandler
        {
             @Override
            public Object invoke(Object proxy, Method method, Object[] args)
                    throws Throwable {
                 return null;
            }
         }
        Collection proxy1=(Collection) ct.newInstance(new MyinvocationHandler());
     }}

法二:用new方法直接创建代理类实例对象

Object target=new Object ();
Object proxy1=Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(), new InvocationHandler(){

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

Class<?> []cs={Collection.class};
Collection proxy3=(Collection)Proxy.newProxyInstance
        (Collection.class.getClassLoader(),
          cs,new MyinvocationHandler());
Collection proxy4=(Collection)Proxy.newProxyInstance
        (Collection.class.getClassLoader(),
         new Class[] {Collection.class},
         new MyinvocationHandler());

6.InvocationHandler(接口)

成员方法:

Object invoke(Object proxy, Method method, Object[] args);//在代理实例上处理方法调用并返回结果。

事实上,Proxy代理类对象调用(该接口上的)方法时,其实是去调用了handler的

invoke方法。对于不是该接口上的方法,如getClass(),则调用它本身的,不用委托handler去调用invoke方法。

7.代理类的模式

以面向对象的思想处理AOP(面向方面编程)的业务,即在实现代理的系统功能时,将目标类对象和接口(该接口通常以实现接口某个类的方式传入,实现接口里的方法(系统功能)的类)作为参数传入一个要实现系统功能的方法中。

        ArrayList al=new ArrayList();
        Collection proxy4=(Collection)getProxy(al,new Myadvice());
        proxy4.add("hq");
    //以下是封装了实现代理功能的一个方法
    //参数:目标类对象,和接口(实现代理功能的类,类里有实现功能的方法),该接口通常以实现接口某个类的方式传入。
    private static Object getProxy(final Object target,final interfaceAdvice advice) {
         Object proxy=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 obj=method.invoke(target, args);
                         advice.afterMethod(method);
                         return obj;
                    }
                });
         return proxy;
    }

8.实现AOP功能的封装与配置

工厂类BeanFactory负责创建目标类或代理类的实例对象,并通过配置文件实现切换。其getBean方法根据参数字符串返回一个相应的实例对象,如果参数字符串在配置文件中对应的类名不是ProxyFactoryBean,则直接返回该类的实例对象,否则,返回该类实例对象的getProxy方法返回的对象。
BeanFactory的构造方法接收代表配置文件的输入流对象,配置文件格式如下:
    #xxx=java.util.ArrayList
    xxx=cn.itcast.ProxyFactoryBean
    xxx.target=java.util.ArrayList
    xxx.advice=cn.itcast.MyAdvice
ProxyFacotryBean充当封装生成动态代理的工厂,需要为工厂类提供哪些配置参数信息?
目标:target
通知:advice
编写客户端应用:
编写实现Advice接口的类和在配置文件中进行配置
调用BeanFactory获取对象

时间: 2024-10-06 00:28:50

Java-动态代理技术的相关文章

Java——动态代理技术

1.程序中的代理 为具有相同接口的目标类的各个方法,添加一些系统功能,如日志,异常处理,计算方法运行的 时间,事务管理等等,都可以交给另一个类去实现这些功能,该类称为代理类. 注意:为了让代理类共享目标类中的各个方法,可以让代理类实现和目标类相同的接口. public class AProxy { //AProxy类为A的代理类,可以计算sayHi方法的运行时间 public void getTime() { //方法开始前时间 new A().sayHi(); //方法结束后时间 } } cl

java动态代理技术

主要用来做方法的增强.让你能够在不改动源代码的情况下,增强一些方法,在方法运行前后做不论什么你想做的事情(甚至根本不去运行这种方法).由于在InvocationHandler的invoke方法中,你能够直接获取正在调用方法相应的Method对象.详细应用的话.比方能够加入调用日志,做事务控制等. 另一个有趣的作用是能够用作远程调用,比方如今有Java接口,这个接口的实现部署在其他server上,在编写client代码的时候,没办法直接调用接口方法,由于接口是不能直接生成对象的,这个时候就能够考虑

代理模式 &amp; Java原生动态代理技术 &amp; CGLib动态代理技术

第一部分.代理模式  代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务.(其实就是在代理类中关联一个委托类的实例,然后在代理类中进行包装). UML图如下: 第二部分.在Java中实现代理模式  按照代理的创建时期,代理类可以分

Java中动态代理技术生成的类与原始类的区别 (转)

用动态代理的时候,对它新生成的类长什么样子感到好奇.有幸通过一些资料消除了心里的疑惑. 平时工作使用的Spring框架里面有一个AOP(面向切面)的机制,只知道它是把类重新生成了一遍,在切面上加上了后来定义的逻辑.这样就达到了动态的在原有类上增加一些功能.比如日志打印,拦截信息等. 这里只关心动态代理技术生成新的类,先不管虚拟机是如何去生成类,用了什么字节码生成技术,怎么产生字节码等这一系列动作.现在只关心最后生成的新类长什么样,它和老类有什么区别.为了获取到生成后的代理类的字节码并且反编译成我

java动态代理原理及解析

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

java 动态代理模式

一.相关类及其方法:java.lang.reflect.Proxy,Proxy 提供用于创建动态代理类和实例的静态方法.newProxyInstance()返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序(详见api文档) java.lang.reflect.InvocationHandler,InvocationHandler 是代理实例的调用处理程序 实现的接口.invoke()在代理实例上处理方法调用并返回结果.在与方法关联的代理实例上调用方法时,将在调用处理程序

Java动态代理浅度分析

前言: 我在工作中遇到一种情况:有些程序员在面试的时候对知识点掌握的很优秀,而写代码却很吃力,他们往往侧重于知识本身,对应用略有不足,就像空有一把利剑,却不会使用一样,于是乎就想写一些不一样的文章,内容可能很白,重点是在整个讲解过程中的切入角度以及思考方式. 本文和别的文章有所不同,不从底层次来分析动态代理,仅仅为了程序员在工作中使用. 正文: 先写一个简单的案例,引出来动态代理. 假使我们项目中有对用户删除的业务处理,放在业务层中(尽量做到面向接口编程,测试类很有必要贴出来) 原始代码:定义接

Java动态代理简单应用

概念 代理模式是基本的设计模式之一,它是开发者为了提供额外的或不同的操作,而插入的用来代替“实际”对象的对象.这些操作通常涉及与“实际”对象的通信,因此代理通常充当着中间人的角色. Java动态代理比代理的思想更进一步,因为它可以动态地创建代理并动态地处理对代理方法的调用.在动态代理上所做的所有调用都会被重定向到单一的调用处理器(InvocationHandler)上,调用处理器的工作是揭示调用的类型并确定相应的策略. Java动态代理实现机制采用了反射的思想,有关于反射的基础知识,可以参见博客

【转载】Java 动态代理

Java 动态代理 本文为 Android 开源项目源码解析 公共技术点中的 动态代理 部分项目地址:Jave Proxy,分析的版本:openjdk 1.6,Demo 地址:Proxy Demo分析者:Caij,校对者:Trinea,校对状态:完成 1. 相关概念 1.1 代理 在某些情况下,我们不希望或是不能直接访问对象 A,而是通过访问一个中介对象 B,由 B 去访问 A 达成目的,这种方式我们就称为代理.这里对象 A 所属类我们称为委托类,也称为被代理类,对象 B 所属类称为代理类.代理

Java动态代理--&gt;Spring AOP

引述要学习Spring框架的技术内幕,必须事先掌握一些基本的Java知识,正所谓“登高必自卑,涉远必自迩”.以下几项Java知识和Spring框架息息相关,不可不学(我将通过一个系列分别介绍这些Java基础知识,希望对大家有所帮助.): [1] Java反射知识-->Spring IoC :http://www.iteye.com/topic/1123081 [2] Java动态代理-->Spring AOP :http://www.iteye.com/topic/1123293 [3] 属性