空对象的贯彻,Java代理形式

来源:http://www.smjxgs.com 作者:王中王鉄算盘 人气:61 发布时间:2019-08-08
摘要:【Java SE】动态代理 空对象的兑现,javase import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.util.Arrays;import java.util.Collections;import java.util.List;publi

【Java SE】动态代理 空对象的兑现,javase

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class NullRobot {
    public static void main(String[] args) {
        //1
        Robot r = newNullRobot();
        if(Null.class.isInstance(r)){
//        if(r instanceof Null){ //another way
            System.out.println("[NullRobot]");
        }
        System.out.println(r.name());
        List<Oper> l = r.ops();
        for (Oper oper : l) {
            System.out.println(oper.comm());
        }

        //2
        Robot r2 = (Robot) new NullRobotProxyHandler().bind(null);
        if(Null.class.isInstance(r2)){
            System.out.println("[NullRobot]");
        }
        System.out.println(r2.name());
        List<Oper> l2 = r2.ops();
        for (Oper oper : l2) {
            System.out.println(oper.comm());
        }
    }

    public static Robot newNullRobot(){
        return (Robot) Proxy.newProxyInstance(
                NullRobot.class.getClassLoader(), //classLoader可以传入哪些?满足什么条件的classLoader可以被用来加载代理类
                new Class[]{Robot.class, Null.class}, 
                new NullRobotProxyHandler());
    }
}

interface Null{}

class NullRobotProxyHandler implements InvocationHandler{

//    Robot proxied = 
    class NRobot implements Robot
    , Null //事实上,可以不继承Null接口,而只要Proxy.newProxyInstance()中的Class[]包含Null.class即可使instanceof判断为true
    {
        private String name = "NoneName";
        @Override
        public String name() {
            // TODO Auto-generated method stub
            return name;
        }
        @Override
        public List<Oper> ops() {
            // TODO Auto-generated method stub
            return Collections.emptyList();
        }
    }

    //===another bind way binding real obj with proxy
    public Object bind(Object realObj){
        realObj = new NRobot();
        return (Robot) Proxy.newProxyInstance(
                realObj.getClass().getClassLoader(), 
                realObj.getClass().getInterfaces(), 
                this);
    }

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

}

interface Oper{
    String comm();
}
interface Robot{
    String name();
    List<Oper> ops();
}
class SnowRobot implements Robot{

    private String name ;
    public SnowRobot(String name){
        this.name = name;
    }
    @Override
    public String name() {
        // TODO Auto-generated method stub
        return name;
    }

    @Override
    public List<Oper> ops() {
        // TODO Auto-generated method stub
        return Arrays.asList(new Oper(){
            @Override
            public String comm() {
                // TODO Auto-generated method stub
                return name  " do1";
            }
        },new Oper(){
            @Override
            public String comm() {
                // TODO Auto-generated method stub
                return name " do2";
            }
        });
    }

}

 

SE】动态代理 空对象的贯彻,javase import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util....

jdk动态代理,jdk动态

package com.itcast.day3;

import java.io.ObjectInputStream.GetField;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
/**
 * 通过反射打印出  代理类的 构造函数、方法以及其参数列表
 * @author liujl
 *
 */
public class ProxyTest {

 public static void main(String[] args) throws Exception{
  Class clazzProxy=Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
  System.out.println(clazzProxy);

  System.out.println("---------------begin constructors list-----------------");
  Constructor[] constructors=clazzProxy.getConstructors();
  for(Constructor constructor:constructors){
   String name=constructor.getName();
   StringBuilder sb=new StringBuilder(name);
   sb.append("(");
    Class[] clazzParams=constructor.getParameterTypes();
    for(Class clazzParam:clazzParams){
     sb.append(clazzParam.getName());
    }
   if(clazzParams!=null&&clazzParams.length!=0)
    sb.deleteCharAt(sb.length()-1);
   sb.append(")");
   System.out.println(sb);
  }


  System.out.println("---------------begin methods list-----------------");
  Method[] methods=clazzProxy.getMethods();
  for(Method method:methods){ 
   String name=method.getName();
   StringBuilder sb=new StringBuilder(name);
   sb.append("(");
    Class[] clazzParams=method.getParameterTypes();
    for(Class clazzParam:clazzParams){
     sb.append(clazzParam.getName()).append(",");
    }
   if(clazzParams!=null&&clazzParams.length!=0)
    sb.deleteCharAt(sb.length()-1);
   sb.append(")");
   System.out.println(sb);
  }


  System.out.println("---------------begin create instance object----------------");
//  clazzProxy.newInstance();//这样不行,这样只会掉那个不带参数的构造方法,而代理对象没有无参构造


  //第一种方式创建实例
  Constructor constructor=clazzProxy.getConstructor(InvocationHandler.class);
  class MyInvocationHander1 implements InvocationHandler{

   @Override
   public Object invoke(Object proxy, Method method, Object[] args)
     throws Throwable {

    return null;
   }

  }
  Collection proxy1=(Collection) constructor.newInstance(new MyInvocationHander1());
  System.out.println(proxy1.toString());
  proxy1.clear();
//  proxy1.size();//java.lang.NullPointerException


  //第二种方式创建实例
  Collection proxy2=(Collection)constructor.newInstance(new InvocationHandler(){
   @Override
   public Object invoke(Object proxy, Method method, Object[] args)
     throws Throwable {

    return null;
   }
  });





  //第三种方式创建代理类的实例,  得到Class  和  创建实例对象  一步到位
  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 {
     StringBuilder sbMethodAndParams=new StringBuilder();
     sbMethodAndParams.append(method.getName()).append("(");
     if(args!=null){
      for(Object obj : args){
       sbMethodAndParams.append(obj.toString()).append(",");
      }
      if(args!=null&&args.length!=0){
       sbMethodAndParams.deleteCharAt(sbMethodAndParams.length()-1);
      }
     }
     sbMethodAndParams.append(")");
     System.out.println(sbMethodAndParams);

     long beginTime=System.currentTimeMillis();
     Object retVal=method.invoke(target, args);
     long endTime=System.currentTimeMillis();
     System.out.println(method.getName() "执行时间 " (endTime-beginTime) " 毫秒");
     return retVal;
    }
  });

  proxy3.clear();

  proxy3.add("ljl");
  proxy3.add("wiseq");
  proxy3.add("traits");
  System.out.println("集合元素的个数=" proxy3.size());

  //Proxy也是肯定继承自Object  ,  
  //proxy3.getClass()为啥不调用目标类的getClass()得到ArrayList的字节码? 
  //那是因为Object只有三个方法委托给了InvocationHander,  分别是 toString 、hashCode 、 equals   ,而getClass()方法,生成的代理类有自己的实现
  System.out.println(proxy3.getClass().getName());


 }

}

 

4887王中王鉄算盘奖结果 1

把切面包车型大巴诀要以目的的秘诀封装,把对象传递给代理对象,代理对象实行传入的对象方法 就等于实行了断面包车型地铁代码

 

 

想上边我们看到的硬编码格局的动态代理在事实上的开支中是没有另外意义的,要变的更有用,必要将一部分事物收取去,完成参数化 代理

 

4887王中王鉄算盘奖结果 2

package com.itcast.day3;import java.io.ObjectInputStream.GetField;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationHandler;import...

 

java代理格局及动态代理类

1.      代理形式

代办形式的功效是:为任何对象提供一种代理以决定对这一个指标的拜会。在好几景况下,一个客户不想要么无法直接援引另三个目的,而代理对象能够在客户端和指标对象之间起到中介的职能。

代理情势相似涉及到的剧中人物有:

虚幻剧中人物:注明真实对象和代办对象的一块儿接口;

代办剧中人物:代理对象角色里面含有对真正对象的援用,进而得以操作实际对象,同一时间代理对象提供与诚实对象同样的接口以便在任哪天刻都能代替真实对象。同有时间,代理对象足以在施行实际对象操作时,附加别的的操作,也等于对真正对象举行打包。

实际角色:代理剧中人物所表示的真实性对象,是我们最终要援引的对象。(参见文献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();

       }

    private void preRequest()

    {

        //something you want to do before requesting

    }

    private void postRequest()

    {

        //something you want to do after requesting

    }

}

客户端调用:

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)。在其实应用时,第2个参数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,由它接管实际的劳作。(参见文献3)

    在应用动态代理类时,大家无法不实现InvocationHandler接口,以率先节中的示例为例:

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

public interface Subject

{

   abstract public void request();

}

现实角色RealSubject:同上;

代理剧中人物:

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[]4887王中王鉄算盘奖结果, 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();

      //以下是表明步骤

      /*

      Class c = Proxy.getProxyClass(cls.getClassLoader(),cls.getInterfaces()) ;

      Constructor ct=c.getConstructor(new Class[]{InvocationHandler.class});

      Subject subject =(Subject) ct.newInstance(new Object[]{ds});

     */

     //以下是叁遍性生成

      Subject subject = (Subject) Proxy.newProxyInstance(cls.getClassLoader(),

                       cls.getInterfaces(),ds );

 

      subject.request();

}

       通过这种方法,被代理的目的(RealSubject)能够在运维时动态退换,需求调节的接口(Subject接口)能够在运转时退换,调整的法子(DynamicSubject类)也能够动态改换,进而达成了特别灵活的动态代理关系(参见文献2)。

 原版的书文地址:

 

Java动态代理一——动态类Proxy的运用

1.如何是动态代理?

答:动态代理能够提供对另一个指标的拜见,同一时候遮蔽实际目的的现实事实。代理一般会落实它所代表的实际上目的的接口。代理能够访谈实际指标,不过延迟达成实际目的的有的机能,实际指标达成系统的实际意义,代理对象对客户遮蔽了实际上目的。客户不明白它是与代理打交道还是与实际指标打交道。
2.怎么使用动态代理?

答:因为动态代理能够对央浼实行任何管理

3.接纳它有哪些好处?

答:因为动态代理能够对央浼进行其余管理
4.哪些地点须要动态代理?

答:不一致意直接待上访谈一些类;对拜访要做极度管理等

 

时下Java开拓包中涵盖了对动态代理的帮忙,不过其促成只协理对接口的的贯彻。 其促成入眼透过java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。 

Proxy类首要用来赢得动态代理对象,InvocationHandler接口用来约束调用者完结

以下为仿照案例,通过动态代理达成在章程调用前后向决定台出口两句字符串

目录结构

4887王中王鉄算盘奖结果 3

<br/>

概念二个HelloWorld接口

4887王中王鉄算盘奖结果 4

1 package com.ljq.test;
2
3  /**
4 * 定义贰个HelloWorld接口
5 *
6 * @author jiqinlin
7 *
8 */
9  public interface HelloWorld {
10 public void sayHelloWorld();
11 }

4887王中王鉄算盘奖结果 5

<br/>

类HelloWorldImpl是HelloWorld接口的完结

4887王中王鉄算盘奖结果 6

1 package com.ljq.test;
2
3  /**
4 * 类HelloWorldImpl是HelloWorld接口的落成
5 *
6 * @author jiqinlin
7 *
8 */
9  public class HelloWorldImpl implements HelloWorld{
10
11 public void sayHelloWorld() {
12 System.out.println("HelloWorld!");
13 }
14
15 }

4887王中王鉄算盘奖结果 7

HelloWorldHandler是 InvocationHandler接口达成

4887王中王鉄算盘奖结果 8

1 package com.ljq.test;
2
3  import java.lang.reflect.InvocationHandler;
4  import java.lang.reflect.Method;
5
6  /**
7 * 实现在艺术调用前后向调控台出口两句字符串
8 *
9 * @author jiqinlin
10 *
11 */
12  public class HelloWorldHandler implements InvocationHandler{
13 //要代理的原本对象
14   private Object obj;
15
16 public HelloWorldHandler(Object obj) {
17 super();
18 this.obj = obj;
19 }
20
21 /**
22 * 在代理实例上拍卖措施调用并重临结果
23 *
24 * @param proxy 代理类
25 * @param method 被代理的法子
26 * @param args 该措施的参数数组
27 */
28 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
29 Object result = null;
30 //调用从前
31   doBefore();
32 //调用原始对象的法子
33 result=method.invoke(obj, args);
34 //调用之后
35 doAfter();
36 return result;
37 }
38
39 private void doBefore(){
40 System.out.println("before method invoke");
41 }
42
43 private void doAfter(){
44 System.out.println("after method invoke");
45 }
46
47 }

4887王中王鉄算盘奖结果 9

测试类

4887王中王鉄算盘奖结果 10

package com.ljq.test;

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

public class HelloWorldTest {

public static void main(String[] args) {
HelloWorld helloWorld=new HelloWorldImpl();
InvocationHandler handler=new HelloWorldHandler(helloWorld);

//创设动态代理对象
HelloWorld proxy=(HelloWorld)Proxy.newProxyInstance(
helloWorld.getClass().getClassLoader(),
helloWorld.getClass().getInterfaces(),
handler);
proxy.sayHelloWorld();
}
}

4887王中王鉄算盘奖结果 11

 4887王中王鉄算盘奖结果 12

初稿地址:

 

本文由4887王中王鉄算盘奖结果发布于王中王鉄算盘,转载请注明出处:空对象的贯彻,Java代理形式

关键词:

上一篇:Java深入研究

下一篇:没有了

最火资讯