Java 动态代理机制详解

在上学Spring的时候,大家领会Spring主要有两大理念,三个是IoC,另三个正是AOP,对于IoC,重视注入就不要多说了,而对此Spring的宗旨AOP来讲,大家不止要精晓怎么通过AOP来满足的大家的功效,大家更亟待学习的是其底层是何许的一个原理,而AOP的原理正是java的动态代理体制,所以本篇小说正是对java的动态机制举办八个回想。

在java的动态代理体制中,有多少个重要的类或接口,一个是
InvocationHandler(Interface卡塔尔(قطر‎、另一个则是
Proxy(Class卡塔尔,那三个类和接口是落实大家动态代理所不可不运用的。首先大家先来探视java的API帮衬文书档案是何等对那五个类进行描述的:

澳门新浦京8455com,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

我们看看这一个方式一共收受八个参数,那么那四个参数分别代表如何呢?

  • 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.

其一法子的效果便是赢得三个动态的代办对象,其摄取四个参数,我们来看看那四个参数所表示的意义:

  • 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(State of Qatar.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中的动态代理体制,那一个知识点特别丰硕的严重性,蕴含大家Spring的AOP其不畏经过动态代理的机制完成的,所以大家应当要美貌的掌握动态代理的建制。

You can leave a response, or trackback from your own site.

Leave a Reply

网站地图xml地图