导航:首页 > 编程语言 > 代理模式java动态

代理模式java动态

发布时间:2022-07-28 20:43:21

❶ 如何使用Proxy模式及java内建的动态代理机制

在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的我们的功能,我们更需要学习的是其底层是怎么样的一个原理,而AOP的原理就是java的动态代理机制,所以本篇随笔就是对java的动态机制进行一个回顾。
在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的。首先我们先来看看java的API帮助文档是怎么样对这两个类进行描述的:
InvocationHandler:
InvocationHandler is the interface implemented by the invocation handler of a proxy instance.

Each proxy instance has an associated invocation handler. When a method is invoked on a proxy instance, the method invocation is encoded and dispatched to the invoke method of its invocation handler.

每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。我们来看看InvocationHandler这个接口的唯一一个方法 invoke 方法:
Object invoke(Object proxy, Method method, Object[] args) throws Throwable

我们看到这个方法一共接受三个参数,那么这三个参数分别代表什么呢?
Object invoke(Object proxy, Method method, Object[] args) throws Throwable

proxy:指代我们所代理的那个真实对象
method:指代的是我们所要调用真实对象的某个方法的Method对象
args:指代的是调用真实对象某个方法时接受的参数

如果不是很明白,等下通过一个实例会对这几个参数进行更深的讲解。
接下来我们来看看Proxy这个类:
Proxy provides static methods for creating dynamic proxy classes and instances, and it is also the superclass of all dynamic proxy classes created by those methods.

Proxy这个类的作用就是用来动态创建一个代理对象的类,它提供了许多的方法,但是我们用的最多的就是 newProxyInstance 这个方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
Returns an instance of a proxy class for the specified interfaces that dispatches method invocations to the specified invocation handler.

这个方法的作用就是得到一个动态的代理对象,其接收三个参数,我们来看看这三个参数所代表的含义:

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException

loader:一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载

interfaces:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了

h:一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上

好了,在介绍完这两个接口(类)以后,我们来通过一个实例来看看我们的动态代理模式是什么样的:
首先我们定义了一个Subject类型的接口,为其声明了两个方法:
public interface Subject
{
public void rent();

public void hello(String str);
}

接着,定义了一个类来实现这个接口,这个类就是我们的真实对象,RealSubject类:

public class RealSubject implements Subject
{
@Override
public void rent()
{
System.out.println("I want to rent my house");
}

@Override
public void hello(String str)
{
System.out.println("hello: " + str);
}
}

下一步,我们就要定义一个动态代理类了,前面说个,每一个动态代理类都必须要实现 InvocationHandler 这个接口,因此我们这个动态代理类也不例外:

public class DynamicProxy implements InvocationHandler
{
//这个就是我们要代理的真实对象
private Object subject;

// 构造方法,给我们要代理的真实对象赋初值
public DynamicProxy(Object subject)
{
this.subject = subject;
}

@Override
public Object invoke(Object object, Method method, Object[] args)
throws Throwable
{
//在代理真实对象前我们可以添加一些自己的操作
System.out.println("before rent house");

System.out.println("Method:" + method);

// 当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
method.invoke(subject, args);

//在代理真实对象后我们也可以添加一些自己的操作
System.out.println("after rent house");

return null;
}

}

最后,来看看我们的Client类:

public class Client
{
public static void main(String[] args)
{
// 我们要代理的真实对象
Subject realSubject = new RealSubject();

// 我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法的
InvocationHandler handler = new DynamicProxy(realSubject);

/*
* 通过Proxy的newProxyInstance方法来创建我们的代理对象,我们来看看其三个参数
* 第一个参数 handler.getClass().getClassLoader() ,我们这里使用handler这个类的ClassLoader对象来加载我们的代理对象
* 第二个参数realSubject.getClass().getInterfaces(),我们这里为代理对象提供的接口是真实对象所实行的接口,表示我要代理的是该真实对象,这样我就能调用这组接口中的方法了
* 第三个参数handler, 我们这里将这个代理对象关联到了上方的 InvocationHandler 这个对象上
*/
Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject
.getClass().getInterfaces(), handler);

System.out.println(subject.getClass().getName());
subject.rent();
subject.hello("world");
}
}

我们先来看看控制台的输出:

$Proxy0
before rent house
Method:public abstract void com.xiaoluo.dynamicproxy.Subject.rent()
I want to rent my house
after rent house
before rent house
Method:public abstract void com.xiaoluo.dynamicproxy.Subject.hello(java.lang.String)
hello: world
after rent house

我们首先来看看 $Proxy0 这东西,我们看到,这个东西是由 System.out.println(subject.getClass().getName()); 这条语句打印出来的,那么为什么我们返回的这个代理对象的类名是这样的呢?
Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject
.getClass().getInterfaces(), handler);

可能我以为返回的这个代理对象会是Subject类型的对象,或者是InvocationHandler的对象,结果却不是,首先我们解释一下为什么我们这里可以将其转化为Subject类型的对象?原因就是在newProxyInstance这个方法的第二个参数上,我们给这个代理对象提供了一组什么接口,那么我这个代理对象就会实现了这组接口,这个时候我们当然可以将这个代理对象强制类型转化为这组接口中的任意一个,因为这里的接口是Subject类型,所以就可以将其转化为Subject类型了。
同时我们一定要记住,通过 Proxy.newProxyInstance 创建的代理对象是在jvm运行时动态生成的一个对象,它并不是我们的InvocationHandler类型,也不是我们定义的那组接口的类型,而是在运行是动态生成的一个对象,并且命名方式都是这样的形式,以$开头,proxy为中,最后一个数字表示对象的标号。
接着我们来看看这两句
subject.rent();
subject.hello("world");
这里是通过代理对象来调用实现的那种接口中的方法,这个时候程序就会跳转到由这个代理对象关联到的 handler 中的invoke方法去执行,而我们的这个 handler 对象又接受了一个 RealSubject类型的参数,表示我要代理的就是这个真实对象,所以此时就会调用 handler 中的invoke方法去执行:

public Object invoke(Object object, Method method, Object[] args)
throws Throwable
{
//在代理真实对象前我们可以添加一些自己的操作
System.out.println("before rent house");

System.out.println("Method:" + method);

// 当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
method.invoke(subject, args);

//在代理真实对象后我们也可以添加一些自己的操作
System.out.println("after rent house");

return null;
}

我们看到,在真正通过代理对象来调用真实对象的方法的时候,我们可以在该方法前后添加自己的一些操作,同时我们看到我们的这个 method 对象是这样的:
public abstract void com.xiaoluo.dynamicproxy.Subject.rent()

public abstract void com.xiaoluo.dynamicproxy.Subject.hello(java.lang.String)

正好就是我们的Subject接口中的两个方法,这也就证明了当我通过代理对象来调用方法的时候,起实际就是委托由其关联到的 handler 对象的invoke方法中来调用,并不是自己来真实调用,而是通过代理的方式来调用的。
这就是我们的java动态代理机制

❷ java 我不理解动态代理的意义

人家是动态编程,需要在原来的方法的功能基础上再添加一些功能,而不用改变这个方法的签名,原来调用这个方法的类依然能正常工作。

比如,现在要把一段文本发送给另一个人,普通方法是 void send(File a),现在我们弄出个特性,就像 Spring AOP 那样,在 send 之前给这个 a 压缩一下。原来的程序没有压缩功能,现在我们需要添加的话而不改变原来所有的代码的话就得用类似 AOP 这样的代码来处理。

一般一个无法再继承的类和方法,要用代理,而能够继承的类和方法可以在内在中直接生成一个新的 java 类继承它然后覆盖掉那个 send 方法,像 hibernate/spring/jboss 都把这些自动完成了。
而像 AspectJ 这种 AOP 刚不同,它直接把人家的 class 代码修改了,它就不需要使用代理。

这些在新的 JDK 6 中都可以通过 Instrument 来做到,不过也是个通用的方法,还得通过规则来定制什么情况下处理,什么时候不处理。

❸ java 动态代理怎么理解

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

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

二、静态代理类
如下, HelloServiceProxy 类是代理类,HelloServiceImpl类是委托类,这两个类都实现了HelloService接口。其中HelloServiceImpl类是HelloService接口的真正实现者,而HelloServiceProxy类是通过调用HelloServiceImpl 类的相关方法来提供特定服务的。HelloServiceProxy类的echo()方法和getTime()方法会分别调用被代理的HelloServiceImpl 对象的echo()方法和getTime()方法,并且在方法调用前后都会执行一些简单的打印操作。

由此可见,代理类可以为委托类预处理消息、把消息转发给委托类和事后处理消息等。

例程1 HelloService.java
package proxy;
import java.util.Date;
public interface HelloService{
public String echo(String msg);
public Date getTime();
}
例程2 HelloServiceImpl.java
package proxy;
import java.util.Date;
public class HelloServiceImpl implements HelloService{
public String echo(String msg){
return "echo:"+msg;
}
public Date getTime(){
return new Date();
}
}
例程3 HelloServiceProxy.java
package proxy;
import java.util.Date;
public class HelloServiceProxy implements HelloService{
private HelloService helloService; //表示被代理的HelloService 实例
public HelloServiceProxy(HelloService helloService){
this.helloService=helloService;
}
public void setHelloServiceProxy(HelloService helloService){
this.helloService=helloService;
}
public String echo(String msg){
System.out.println("before calling echo()"); //预处理
String result=helloService.echo(msg); //调用被代理的HelloService 实例的echo()方法
System.out.println("after calling echo()"); //事后处理
return result;
}
public Date getTime(){
System.out.println("before calling getTime()"); //预处理
Date date=helloService.getTime(); //调用被代理的HelloService 实例的getTime()方法
System.out.println("after calling getTime()"); //事后处理
return date;
}
}
在Client1 类的main()方法中,先创建了一个HelloServiceImpl对象,又创建了一个HelloServiceProxy对象,最后调用HelloServiceProxy对象的echo()方法。
例程4 Client1.java
package proxy;
public class Client1{
public static void main(String args[]){
HelloService helloService=new HelloServiceImpl();
HelloService helloServiceProxy=new HelloServiceProxy(helloService);
System.out.println(helloServiceProxy.echo("hello"));
}
}
运行Client1 类,打印结果如下:
before calling echo()
after calling echo()
echo:hello
例程3 的HelloServiceProxy 类的源代码是由程序员编写的,在程序运行前,它的.class文件就已经存在了,这种代理类称为静态代理类。

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

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接口的动态代理类的实例:
/**** 方式一 ****/
//创建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类的静态方法创建的动态代理类的实例具有以下特点:
1. 假定变量foo 是一个动态代理类的实例,并且这个动态代理类实现了Foo 接口,那么“foo instanceof Foo”的值为true。把变量foo强制转换为Foo类型是合法的:
(Foo) foo //合法

2.每个动态代理类实例都和一个InvocationHandler 实例关联。Proxy 类的getInvocationHandler(Object proxy)静态方法返回与参数proxy指定的代理类实例所关联的InvocationHandler 对象。

3.假定Foo接口有一个amethod()方法,那么当程序调用动态代理类实例foo的amethod()方法时,该方法会调用与它关联的InvocationHandler 对象的invoke()方法。

InvocationHandler 接口为方法调用接口,它声明了负责调用任意一个方法的invoke()方法:
Object invoke(Object proxy,Method method,Object[] args) throws Throwable

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

四、最后看一个实例:
HelloServiceProxyFactory 类的getHelloServiceProxy()静态方法负责创建实现了HelloService接口的动态代理类的实例。

例程5 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);
}
}
如下所示的Client2 类先创建了一个HelloServiceImpl 实例,然后创建了一个动态代理类实例helloServiceProxy,最后调用动态代理类实例的echo()方法。
例程6 Client2.java
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"));
}
}
运行Client2,打印结果如下:
动态代理类的名字为$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
从结果看出,动态代理类的名字为$Proxy0。
PostScript

❹ java 动态代理实例

1. 代理模式
代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
代理模式一般涉及到三个角色:
抽象角色:声明真实对象和代理对象的共同接口;
代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。

以下以《Java与模式》中的示例为例:

抽象角色:
abstract public class Subject {
abstract public void request();
}

真实角色:实现了Subject的request()方法。
public class RealSubject extends Subject {
public RealSubject() { }

public void request() {
System.out.println( " From real subject. " );
}
}

代理角色:
public class ProxySubject extends Subject {
private RealSubject realSubject; // 以真实角色作为代理角色的属性

public ProxySubject() { }

public void request() { // 该方法封装了真实对象的request方法
preRequest();

if ( realSubject == null ) {

realSubject = new RealSubject();
}

realSubject.request(); // 此处执行真实对象的request方法

postRequest();
}

客户端调用:
Subject sub = new ProxySubject();
Sub.request();

由以上代码可以看出,客户实际需要调用的是RealSubject类的request()方法,现在用ProxySubject来代理 RealSubject类,同样达到目的,同时还封装了其他方法(preRequest(),postRequest()),可以处理一些其他问题。

另外,如果要按照上述的方法使用代理模式,那么真实角色必须是事先已经存在的,并将其作为代理对象的内部属性。但是实际使用时,一个真实角色必须对应一个 代理角色,如果大量使用会导致类的急剧膨胀;此外,如果事先并不知道真实角色,该如何使用代理呢?这个问题可以通过Java的动态代理类来解决。

2.动态代理类

Java动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类:

(1). Interface InvocationHandler:该接口中仅定义了一个方法Object:invoke(Object obj,Method method, Object[] args)。在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,如上例中的request(),args为该方法的参数数组。 这个抽象方法在代理类中动态实现。

(2).Proxy:该类即为动态代理类,作用类似于上例中的ProxySubject,其中主要包含以下内容:

Protected Proxy(InvocationHandler h):构造函数,估计用于给内部的h赋值。

Static Class getProxyClass (ClassLoader loader, Class[] interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。

Static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)。

所谓Dynamic Proxy是这样一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些 interface。你当然可以把该class的实例当作这些interface中的任何一个来用。当然啦,这个Dynamic Proxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。

在使用动态代理类时,我们必须实现InvocationHandler接口,以第一节中的示例为例:

抽象角色(之前是抽象类,此处应改为接口):

public interface Subject {
abstract public void request();
}

具体角色RealSubject:
public class RealSubject implements Subject {

public RealSubject() {}

public void request() {
System.out.println( " From real subject. " );
}

}

代理处理器:
import java.lang.reflect.Method;

import java.lang.reflect.InvocationHandler;

public class DynamicSubject implements InvocationHandler {
private Object sub;
public DynamicSubject() {}

public DynamicSubject(Object obj) {
sub = obj;
}

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println( " before calling " + method);
method.invoke(sub,args);

System.out.println( " after calling " + method);
return null ;
}

}

该代理类的内部属性为Object类,实际使用时通过该类的构造函数DynamicSubject(Object obj)对其赋值;此外,在该类还实现了invoke方法,该方法中的

method.invoke(sub,args);

其实就是调用被代理对象的将要被执行的方法,方法参数sub是实际的被代理对象,args为执行被代理对象相应操作所需的参数。通过动态代理类,我们可以在调用之前或之后执行一些相关操作。

客户端:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class Client {

static public void main(String[] args) throws Throwable {

RealSubject rs = new RealSubject(); // 在这里指定被代理类
InvocationHandler ds = new DynamicSubject(rs);
Class cls = rs.getClass();

// 以下是一次性生成代理
Subject subject = (Subject) Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(),ds );
subject.request();

}

程序运行结果:
before calling public abstract void Subject.request()
From real subject.
after calling public abstract void Subject.request()

通过这种方式,被代理的对象(RealSubject)可以在运行时动态改变,需要控制的接口(Subject接口)可以在运行时改变,控制的方式(DynamicSubject类)也可以动态改变,从而实现了非常灵活的动态代理关系。

❺ java语言中的代理模式(请举例)

动态代理,通过JAVA反射机制实现的。HIBERNATE中常用。
也可以自己写一个的,可以上网去找找JDK动态代理,理解最好,
SPRING AOP 面向切面编程也会用到!!!

❻ JAVA动态代理设计原理及如何实现

Java动态代理机制的出现,使得Java开发人员不用手工编写代理类,只要简单地制定一组接口及委托类对象,便能动态地获得代理类。代理类会负责将所有的方法调用分配到委托对象上反射执行,配置执行过程中,开发人员还可以进行修改

代理设计模式

代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息、过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。

  1. 为了保持行为的一致性,代理类和委托类通常会实现相同的接口

2. 引入代理能够控制对委托对象的直接访问,可以很好的隐藏和保护委托对象,也更加具有灵活性

代理机制及其特点

首先让我们来了解一下如何使用 Java 动态代理。具体有如下四步骤:

  1. 通过实现 InvocationHandler 接口创建自己的调用处理器;

  2. 通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;

  3. 通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;

  4. 通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。

代理类实例的一些特点

  1. 每个实例都会关联一个InvocationHandler(调用处理器对象),在代理类实例上调用其代理接口中声明的方法时,最终都会由InvocationHandler的invoke方法执行;

  2. java.lang.Object中有三个方法也同样会被分派到调用处理器的 invoke 方法执行,它们是 hashCode,equals 和 toString;

代码示例

最后以一个简单的动态代理例子结束

❼ 什么是java代理模式,具体相关的动态代理和静态代理分别是什么举例更好啦~

简单的例子: HelloSpeaker.java

import java.util.logging.*;

public class HelloSpeaker {
private Logger logger = Logger.getLogger(this.getClass().getName());

public void hello(String name) {

logger.log(Level.INFO, "hello method starts...."); //日志记录
System.out.println("Hello, " + name); //!!!!!!!!!!!

logger.log(Level.INFO, "hello method ends...."); //日志记录
}
}

HelloSpeaker在执行hello()方法时,我们希望能记录该方法已经执行以及结束,
最简单的作法就是如上在执行的前后加上记录动作,然而Logger介入了HelloSpeaker中,
记录这个动作并不属于HelloSpeaker,这使得HelloSpeaker的职责加重。

------------------------------------------------------------------------------------------
怎么办,用下面的方法或许好一些:

先定义一个接口:

public interface IHello {
public void hello(String name);
}
------------------------------------------------------------------------------------------
实现该接口

public class HelloSpeaker implements IHello {
public void hello(String name) {
System.out.println("Hello, " + name);
}
}

public class Greeting implements IHello{
public void hello(String name){
System.out.println("Greeting, " + name);
}
}
------------------------------------------------------------------------------------------
实现一个代理对象: HelloProxy

import java.util.logging.*;
public class HelloProxy implements IHello {
private Logger logger = Logger.getLogger(this.getClass().getName());
private IHello helloObject; //被代理对象

public HelloProxy(){}

public HelloProxy(IHello helloObject) {
this.helloObject = helloObject; //把被代理对象传入
}

public void setHelloObject(IHello helloObject){
this.helloObject = helloObject;
}

public IHello getHelloObject(){
return this.helloObject;
}

public void hello(String name) {
logger.log(Level.INFO, "hello method starts...."); //日志记录

helloObject.hello(name); //!!!!!!!!调用被代理对象的方法

logger.log(Level.INFO, "hello method ends...."); //日志记录
}
}

-----------------------------------------------------------------------------------------------------
执行:

IHello helloProxy = new HelloProxy(new HelloSpeaker()); //生成代理对象, 并给它传入一个被代理的对象
helloProxy.hello("world");

//IHello h=factory.getBean("hello"); // IoC
//h.hello("world");

IHello helloProxy = new HelloProxy(new Greeting()); //生成代理对象, 并给它传入一个被代理的对象
helloProxy.hello("world");

-----------------------------------------------------------------------------------------------------

代理对象HelloProxy将代理真正的HelloSpeaker来执行hello(),并在其前后加上记录的动作,
这使得我们的HelloSpeaker在写时不必介入记录动作,HelloSpeaker可以专心于它的职责。

这是静态代理的基本范例,然而,代理对象的一个接口只服务于一种类的对象,而且如果要代理的方法很多,
我们势必要为每个方法进行代理,静态代理在程序规模稍大时就必定无法胜任.

Java在JDK 1.3之后加入协助开发动态代理功能的类,我们不必为特定对象与方法写特定的代理,使用动态代理,
可以使得一个handler服务于各个对象,首先,一个handler必须实现java.lang.reflect.InvocationHandler:

import java.util.logging.*;
import java.lang.reflect.*;

public class LogHandler implements InvocationHandler { //
private Logger logger = Logger.getLogger(this.getClass().getName());
private Object delegate; //被代理的对象

public Object bind(Object delegate) { //自定义的一个方法,用来绑定被代理对象的,返回值为被代理方法的返回值
this.delegate = delegate;
return Proxy.newProxyInstance(
delegate.getClass().getClassLoader(),
delegate.getClass().getInterfaces(),
this); //通过被代理的对象生成它的代理对象, 并同handler绑定在一起
}

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
try {
logger.log(Level.INFO, "method starts..." + method); //日志记录
result = method.invoke(delegate, args); //!!!!!!!!调用被代理对象的方法
logger.log(Level.INFO, "method ends..." + method); //日志记录
} catch (Exception e){
logger.log(Level.INFO, e.toString());
}
return result;
}
}
InvocationHandler的invoke()方法会传入被代理对象的方法名称与参数, 实际上要执行的方法交由method.invoke(),
并在其前后加上记录动作,method.invoke()返回的对象是实际方法执行过后的回传结果。

动态代理必须有接口:
public interface IHello {
public void hello(String name);
}

实现该接口:
public class HelloSpeaker implements IHello {
public void hello(String name) {
System.out.println("Hello, " + name);
}
}

执行:
LogHandler logHandler = new LogHandler();
IHello helloProxy = (IHello) logHandler.bind(new HelloSpeaker()); //传入被代理对象, 传回代理对象
helloProxy.hello("Justin");

❽ java动态代理是什么

import java.lang.reflect.Proxy;
A. 创建一个实现接口InvocationHandler的类,他必须实现invoke方法
B. 创建被代理的类以及接口。
C. 通过Proxy的静态方法newProxyInstance(ClassLoader loader,Class【】interfaces,InvocationHandler handler)创建一个代理
D. 通过代理调用方法。
java动态代理:是在运行是生成的class对象,在生成时必须提供一组或一个interface给它,然后该class就宣称它实现了这些interface。你当然可以把该class的实例当做这些interface中的任何一个来用,当然,这个DynamicProxy其实就是一个Proxy,他不会替你做实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。因此,DynamicProxy必须实现InvocationHandler接口。
5) 一个动态代理了和一个InvocationHandler 实现关联的。每一个动态代理实例的调用都要通过InvocationHandler接口的handler(调用处理器)来调用,动态代理不做任何执行操作,只是在创建动态代理时,把要实现的接口和handler关联,动态代理要帮助被代理执行的任务,要转交给handler来执行。其实就是调用invoke方法。

❾ Java 动态代理如何扩

代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.
这里使用到编程中的一个思想:不要随意去修改别人已经写好的代码或者方法,如果需改修改,可以通过代理的方式来扩展该方法

举个例子来说明代理的作用:假设我们想邀请一位明星,那么并不是直接连接明星,而是联系明星的经纪人,来达到同样的目的.明星就是一个目标对象,他只要负责活动中的节目,而其他琐碎的事情就交给他的代理人(经纪人)来解决.这就是代理思想在现实中的一个例子

用图表示如下:

/**
*测试类
*/
publicclassApp{
publicstaticvoidmain(String[]args){
//目标对象
UserDaotarget=newUserDao();
//代理对象,把目标对象传给代理对象,建立代理关系
UserDaoProxyproxy=newUserDaoProxy(target);
proxy.save();//执行的是代理的方法
}
}

❿ Java代理的三种模式有什么

Java的三种代理模式简述

本文着重讲述三种代理模式在java代码中如何写出,为保证文章的针对性,暂且不讨论底层实现原理,具体的原理将在下一篇文章中讲述。

代理模式是什么

代理模式是一种设计模式,简单说即是在不改变源码的情况下,实现对目标对象的功能扩展。

比如有个歌手对象叫Singer,这个对象有一个唱歌方法叫sing()。

假如你希望,通过你的某种方式生产出来的歌手对象,在唱歌前后还要想观众问好和答谢,也即对目标对象Singer的sing方法进行功能扩展。

但是往往你又不能直接对源代码进行修改,可能是你希望原来的对象还保持原来的样子,又或许你提供的只是一个可插拔的插件,甚至你有可能都不知道你要对哪个目标对象进行扩展。这时就需要用到java的代理模式了。网上好多用生活中的经理人的例子来解释“代理”,看似通俗易懂,但我觉得不适合程序员去理解。程序员应该从代码的本质入手。

阅读全文

与代理模式java动态相关的资料

热点内容
云服务器app安卓下载 浏览:966
如何查看linux服务器的核心数 浏览:137
交易平台小程序源码下载 浏览:148
程序员记笔记用什么app免费的 浏览:646
java与单片机 浏览:897
服务器内网如何通过公网映射 浏览:478
程序员穿越到宋代 浏览:624
怎么使用云服务器挂游戏 浏览:618
真实的幸福pdf 浏览:344
d盘php调用c盘的mysql 浏览:266
怎么样搭建源码网站 浏览:429
新概念四册pdf 浏览:363
怎么下载悦虎检测app 浏览:530
cad表达式命令 浏览:200
程序员去一个小公司值不值得 浏览:848
程序员做个程序多少钱 浏览:497
win10原始解压软件 浏览:321
阿里程序员的老家 浏览:260
量子加密银行 浏览:195
命令方块获得指令手机 浏览:501