`
xuyuanshuaaa
  • 浏览: 394731 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

java 动态代理类的实现,原理及应用

 
阅读更多
在目前的Java开发包中包含了对动态代理的支持,但是其实现只支持对接口的的实现。

其实现主要通过是java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。

Proxy类主要用来获取动态代理对象,InvocationHandler接口用来约束调用者实现,如下,HelloWorld接口定义的业务方法,HelloWorldImpl是HelloWorld接口的实现,HelloWorldHandler是InvocationHandler接口实现。代码如下:

业务接口:
public interface HelloWorld {

       void sayHelloWorld() ;

}

业务接口实现:
public class HelloWorldImpl implements HelloWorld {

       public void sayHelloWorld() {

              System.out.println("Hello World!");            

       }

}

InvocationHandler实现,需要在接口方法调用前后加入一部份处理工作,这里仅仅在方法调用前后向后台输出两句字符串,其代码如下:
import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

public class HelloWorldHandler implements InvocationHandler {

       //要代理的原始对象

       private Object objOriginal;

       /**

        * 构造函数。

        * @param obj 要代理的原始对象。

        */

       public HelloWorldHandler(Object obj) {

              this.objOriginal = obj ;

       }

       public Object invoke(Object proxy, Method method, Object[] args)

                     throws Throwable {

             

              Object result ;

             

        //方法调用之前

              doBefore();

             

        //调用原始对象的方法

              result = method.invoke(this.objOriginal ,args);

             

        //方法调用之后

              doAfter();

             

              return result ;

       }

      

       private void doBefore() {

              System.out.println("before method invoke!");

       }

      

       private void doAfter() {

              System.out.println("after method invoke!");

       }

}

测试代码:
import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Proxy;

 

 

 

public class Test {

 

 

 

       public static void main(String[] args) {

 

 

 

              HelloWorld hw = new HelloWorldImpl();

             

              InvocationHandler handler = new HelloWorldHandler(hw);

             

              HelloWorld proxy = (HelloWorld) Proxy.newProxyInstance(

                            hw.getClass().getClassLoader(),

                            hw.getClass().getInterfaces(),

                            handler);

              proxy.sayHelloWorld();

       }

}

Ø         首先获取一个业务接口的实现对象;

Ø         获取一个InvocationHandler实现,此处是HelloWorldHandler对象;

Ø         创建动态代理对象;

Ø         通过动态代理对象调用sayHelloWorld()方法,此时会在原始对象HelloWorldImpl. sayHelloWorld()方法前后输出两句字符串。

运行测试类输出如下:
before method invoke!

Hello World!

after method invoke!

此处Test类中的方法调用代码比较多,在我们的实际应用中可以通过配置文件来来简化客户端的调用实现。另外也可以通过动态代理来实现简单的AOP。
               

1. 代理模式

代理模式是常用的Java设计模式,它的特征是代理类与委托类有同样的接口,如下图所示。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
按照代理类的创建时期,代理类可分为两种。

◆静态代理类:由程序员创建或由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。

◆动态代理类:在程序运行时,运用反射机制动态创建而成。

2.动态代理类

与静态代理类对照的是动态代理类,动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java反射机制可以生成任意类型的动态代理类。java.lang.reflect包中的Proxy类和 InvocationHandler接口提供了生成动态代理类的能力。

2.1 Proxy类

Proxy类提供了创建动态代理类及其实例的静态方法。

(1)getProxyClass()静态方法负责创建动态代理类,它的完整定义如下:
public static Class getProxyClass(ClassLoader loader, Class[] interfaces)
                                 throws IllegalArgumentException


参数loader指定动态代理类的类加载器,参数interfaces指定动态代理类需要实现的所有接口。

(2)newProxyInstance()静态方法负责创建动态代理类的实例,它的完整定义如下:
public static Object newProxyInstance(ClassLoader loader,
Class[] interfaces,
InvocationHandler handler)
throws IllegalArgumentException


参数loader指定动态代理类的类加载器,参数interfaces指定动态代理类需要实现的所有接口,参数handler指定与动态代理类关联的 InvocationHandler对象。

举例,以下两种方式都创建了实现Foo接口的动态代理类的实例:
View Code

/**** 方式一 ****/
//创建InvocationHandler对象
InvocationHandler handler = new MyInvocationHandler(...);

//创建动态代理类
Class proxyClass = Proxy.getProxyClass(
Foo.class.getClassLoader(), new Class[] { Foo.class });
//创建动态代理类的实例
Foo foo = (Foo) proxyClass.getConstructor( new Class[] { InvocationHandler.class}).
newInstance(new Object[] { handler });

/**** 方式二 ****/
//创建InvocationHandler对象
InvocationHandler handler = new MyInvocationHandler(...);

//直接创建动态代理类的实例
Foo foo = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
new Class[] { Foo.class },
handler);

由Proxy类的静态方法创建的动态代理类具有以下特点:

◆动态代理类是public、final和非抽象类型的;
◆动态代理类继承了java.lang.reflect.Proxy类;
◆动态代理类的名字以“$Proxy”开头;
◆动态代理类实现getProxyClass()和newProxyInstance()方法中参数interfaces指定的所有接口;
◆Proxy类的isProxyClass(Class cl)静态方法可用来判断参数指定的类是否为动态代理类。只有通过Proxy类创建的类才是动态代理类;
◆动态代理类都具有一个public类型的构造方法,该构造方法有一个InvocationHandler类型的参数。

由Proxy类的静态方法创建的动态代理类的实例具有以下特点:

◆假定变量foo是一个动态代理类的实例,并且这个动态代理类实现了Foo接口,那么“foo instanceof Foo”的值为true。把变量foo强制转换为Foo类型是合法的:(Foo) foo   //合法

◆每个动态代理类实例都和一个InvocationHandler实例关联。Proxy类的getInvocationHandler(Object proxy)静态方法返回与参数proxy指定的代理类实例所关联的InvocationHandler对象。
◆假定Foo接口有一个amethod()方法,那么当程序调用动态代理类实例foo的amethod()方法时,该方法会调用与它关联的InvocationHandler对象的invoke()方法。

2.2 InvocationHandler接口

InvocationHandler接口为方法调用接口,它声明了负责调用任意一个方法的invoke()方法:

Object invoke(Object proxy,Method method,Object[] args) throws Throwable

参数proxy指定动态代理类实例,参数method指定被调用的方法,参数args指定向被调用方法传递的参数,invoke()方法的返回值表示被调用方法的返回值。

2.3 举例

如下图所示,HelloServiceProxyFactory类(如例程10-15所示)的getHello- ServiceProxy()静态方法负责创建实现了HelloService接口的动态代理类的实例。

http://new.51cto.com/files/uploadimg/20070212/105519704.jpg

例  HelloServiceProxyFactory.java

package proxy;
import java.lang.reflect.*;

public class HelloServiceProxyFactory {
/** 创建一个实现了HelloService接口的动态代理类的实例
* 参数helloService引用被代理的HelloService实例
*/
public static HelloService getHelloServiceProxy(final HelloService helloService){
//创建一个实现了InvocationHandler接口的匿名类的实例
InvocationHandler handler=new InvocationHandler(){
public Object invoke(Object proxy,
Method method,
Object args[])
throws Exception{
System.out.println("before calling "+method); //预处理
Object result=method.invoke(helloService,args);

//调用被代理的HelloService实例的方法
System.out.println("after calling "+method); //事后处理
return result;
}
};

Class classType=HelloService.class;
return (HelloService)Proxy.newProxyInstance(classType.getClassLoader(),
new Class[]{classType},
handler);
}//# getHelloServiceProxy()
}


如下所示的Client2类先创建了一个HelloServiceImpl实例,然后创建了一个动态代理类实例helloServiceProxy,最后调用动态代理类实例的echo()方法。

package proxy;
public class Client2{
public static void main(String args[]){
HelloService helloService=new HelloServiceImpl();
HelloService helloServiceProxy=
HelloServiceProxyFactory.getHelloServiceProxy(helloService);
System.out.println("动态代理类的名字为"
+helloServiceProxy.getClass().getName());
System.out.println(helloServiceProxy.echo("Hello"));
}
}

打印结果如下:

动态代理类的名字为$Proxy0
before calling public abstract java.lang.
String proxy.HelloService.echo(java.lang.String)
after calling public abstract java.lang.
String proxy.HelloService.echo(java.lang.String)
echo:Hello


能在运行过程中根据接口的类型动态的调用实现该接口的类
动态代理的主要作用就是:实现了日志和业务的分开,也就是某个类只是要提供了某些业务,比如银行取款业务。
这个类实现了取款业务的同时也需要实现日志功能,如果不用动态代理的话,那么由此一来该类代码里面已经额外地添加了自己不该添加的日志功能能代码。所以我们就得使用动态代理把它的业务代码和日志功能代码分开。所以用到了动态代理概念,spring里面的AOP就是一个很好的例子。
动态代理主要是在运行时期创建一个实现一组特定接口的代理类,拦截对目标对象方法的调用..

分享到:
评论

相关推荐

    java 简答可复用动态代理类

    - `Proxy`类是Java提供的动态代理的工厂,它可以根据一个接口生成实现了该接口的代理类的对象。这个代理类会动态地生成并实现接口的所有方法。 - `InvocationHandler`接口定义了一个处理方法调用的回调方法`invoke...

    JAVA实现动态代理的简单流程

    动态代理,顾名思义,是在运行时动态创建代理对象的一种机制,它无需在编译期就确定代理类的具体实现,而是通过反射等技术在运行时自动生成代理类,从而达到灵活扩展原有接口功能的目的。这种机制广泛应用于AOP...

    Java动态代理(Spring Aop原理)

    Java动态代理是Java提供的一种在运行时创建代理对象的技术,它是通过实现InvocationHandler接口和使用Proxy类来实现的。在Spring框架中,AOP(面向切面编程)就是基于Java动态代理来完成的,用于实现横切关注点,如...

    java动态代理 经典文章(word 2007格式的)

    - `Java动态代理模式.docx`可能详细讲解了动态代理模式的原理和实现,包括如何创建代理对象和实现`InvocationHandler`。 - `动态代理详解.docx`则可能深入讨论了Java动态代理的细节,包括实际应用场景和常见问题。...

    反射实现 AOP 动态代理模式(Spring AOP 的实现原理)

    JDK动态代理要求被代理类必须实现一个接口,代理类会实现相同的接口。 Spring框架中的AOP模块使用了动态代理来实现AOP概念。Spring AOP允许开发者定义切面,并在这些切面中指定拦截的方法。Spring AOP支持不同的...

    java动态代理

    - `ClassLoader loader`:指定代理类的类加载器。 - `Class[] interfaces`:指定被代理接口的数组。 - `InvocationHandler h`:指定处理程序。 2. **`InvocationHandler`接口**:定义了一个`invoke`方法,当调用...

    Java动态代理实现数据源连接池

    接下来,我们需要创建一个代理类,该类实现`InvocationHandler`接口,并且在`invoke()`方法内处理数据库连接的生命周期。这可能包括以下步骤: 1. **获取连接**:在代理方法执行前,从连接池中获取一个数据库连接。...

    Java动态代理案例演示代码

    Java动态代理是Java语言提供的一种强大的机制,它允许在运行时创建具有特定接口的代理类对象,这些代理类对象能够对方法调用进行拦截和增强。动态代理在很多场景下非常有用,例如AOP(面向切面编程)、事件监听、...

    Java动态代理学习测试类

    这个“Java动态代理学习测试类”可以帮助我们理解和实践Java动态代理的原理和使用,进一步提升我们对Java语言特性的掌握。通过实际编写和运行代码,我们可以更直观地看到动态代理如何工作,从而更好地应用到实际项目...

    用Java动态代理实现委托模式

    在Java中,动态代理是实现委托模式的一种常见方式,它允许我们在运行时创建具有特定接口的代理类实例。下面我们将详细探讨如何使用Java动态代理实现委托模式,以及相关的源码和工具应用。 首先,理解委托模式的基本...

    Java中的动态代理

    - 接口数组:代理类实现的接口列表。 - InvocationHandler:代理实例内部调用处理器。 ##### 2.2 `java.lang.reflect.InvocationHandler`接口 - **invoke()** 方法:当代理对象的方法被调用时,会自动触发此方法...

    Java中动态代理的介绍及实例

    动态代理是Java反射机制的强大应用之一,通过在运行时动态生成代理类,能够灵活地为已有对象添加新功能,而不需改变其原有结构,极大地提升了程序的灵活性和可扩展性。掌握动态代理的原理和实现方式,对于深入理解...

    用Java实现的代理模式之动态代理

    本篇将重点讨论"动态代理",这是一种在运行时创建代理对象的技术,使得我们可以在程序运行过程中,根据需要动态地生成具有额外功能的代理类。 动态代理主要由Java的`java.lang.reflect.Proxy`类和`java.lang....

    使用java动态代理技术实现简单的AOP切面编程实例

    1. **定义接口**:首先,我们需要定义一个或多个接口,这些接口将被代理类实现。例如,我们可以定义一个名为`Service`的接口,包含业务方法。 2. **实现InvocationHandler**:创建一个类实现`InvocationHandler`接口...

    反射实现 AOP 动态代理模式(Spring AOP 的实现 原理) - Java 例子 -

    在Spring AOP中,`Proxy`类会根据目标对象的接口生成一个代理类,这个代理类会实现目标对象的所有接口,并在每个方法调用前后插入相应的通知。`InvocationHandler`接口定义了一个`invoke`方法,当调用代理对象的方法...

    java动态代理新java动态代理新java动态代理新

    1. **Proxy**:这是一个工具类,用于创建一个实现了一组给定接口的动态代理类。我们可以通过调用 `Proxy.newProxyInstance()` 方法来创建一个动态代理对象。 2. **InvocationHandler**:这是一个接口,它定义了一...

    动态代理原理实例Demo

    动态代理主要有两种实现方式:JDK自带的`java.lang.reflect.Proxy`类和`java.lang.invoke.MethodHandle`API。这里主要讨论JDK的Proxy类,因为这是最常见且相对简单的实现方式。 1. **Proxy类的使用** - **Proxy....

    一个简单的java动态代理的实例

    在Java中,动态代理允许我们在运行时创建代理类,这些代理类可以拦截并扩展目标对象的方法调用。这在处理如日志、事务管理、性能监控等跨切面关注点时非常有用。 `Proxy`类是Java动态代理的工厂,它提供了`...

Global site tag (gtag.js) - Google Analytics