精华内容
下载资源
问答
  • java动态代理

    万次阅读 2020-12-14 17:59:02
    最近在看一些技术源码的时候,发现很多地方都是动态代理, 真可谓是一切皆代理啊,所以我们需要弄明白代理模式这样在看源码的时候会好受很多。 2、基本概念 代理(Proxy)模式提供了间接访问目标对象的方式,即通过...

    1、引言

    最近在看一些技术源码的时候,发现很多地方都是动态代理, 真可谓是一切皆代理啊,所以我们需要弄明白代理模式这样在看源码的时候会好受很多。

    2、基本概念

    代理(Proxy)模式提供了间接访问目标对象的方式,即通过代理对象访问目标对象,这样做的好处是:可以在目标对象的功能上,增加额外的功能补充,即扩展目标对象的功能。

    这就符合了设计模式低开闭原则,即在对既有代码不改动的情况下进行功能扩展。

    举个我们平常非常常见的例子, 明星和经纪人就是被代理和代理的关系,明细出演活动的时候,明细就是一个目标对象,他只负责活动中的节目,而其他的琐碎的事情就交给他的代理人(经纪人)来解决。这就是代理思想 中的一个例子。

    3、静态代理

    静态代理的特点:代理类和目标类必须实现 同一个接口或者继承相同的父类。所以我们需要 定义一个接口。下面来看具体实现demo。

    接口类:

    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1410:28
     */
    public interface Istart {
    
        void sing();
    }

    目标类:

    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1416:07
     */
    public class LDHStar implements Istart {
    
        @Override
        public void sing() {
            System.out.println("华仔唱歌");
        }
    }
    

    代理类:

    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1416:08
     */
    public class StaticPorxyManager implements Istart {
    
        private Istart target;
        public StaticPorxyManager(Istart target) {
            this.target = target;
        }
    
        @Override
        public void sing() {
            System.out.println("演唱会之前。。。。");
            this.target.sing();
            System.out.println("演唱会之后。。。。");
    
        }
    }

    测试类:

    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1410:46
     */
    public class StaticTeasMain {
    
        public static void main(String[] args) {
            Istart ldhStar = new LDHStar();
    
            StaticPorxyManager staticPorxyManager = new StaticPorxyManager(ldhStar);
            staticPorxyManager.sing();
    
        }
    }

    静态代理类优缺点:

    有点:可以在不修改目标代码的情况下,扩折额外 功能

    缺点:因为代理类和目标类必须实现相同的接口,所以会有很多代理类,类太多, 同时,一旦接口增加方法,目标对象很代理对象都需要维护。而动态代理可以解决上面的问题。

    4、JDK动态代理

    动态代理的主要特点就是能够在程序运行时JVM才为目标对象生成代理对象。

    常说的动态代理也叫做JDK 代理也是一种接口代理,之所以叫做接口代理,是因为被代理的对象也就是目标对象必须实现至少一个接口,没有实现接口不能使用这种方式生成代理对象,JDK中生成代理对象的代理类就是Proxy,所在包是java.lang.reflect.

    接口:

    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1410:28
     */
    public interface Istart {
    
        void sing();
    }
    

    目标类:

    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1410:29
     */
    public class WangFengStar implements Istart {
        @Override
        public void sing() {
            System.out.println("汪峰唱歌。。。");
        }
    }
    
    InvocationHandler类:
    import java.lang.annotation.Target;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1410:32
     */
    public class StarInvocationHandler implements InvocationHandler {
    
        private  Object target;
        public StarInvocationHandler(Object target) {
            this.target = target;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
            System.out.println("演唱会前工作");
            //调用目标对象的目标方法
            method.invoke(target,args);
            System.out.println("演唱会后工作");
            return null;
        }
    }
    

    代理工厂:

    import java.lang.reflect.Proxy;
    
    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1410:30
     */
    public class ProxyFactory {
    
        private Object target;
        private StarInvocationHandler starInvocationHandler;
        public ProxyFactory( Object target) {
            this.target = target;
            this.starInvocationHandler = new StarInvocationHandler(target);
        }
    
        public Object getProxyObject(){
           return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),starInvocationHandler);
        }
    }

    测试方法:

    public class TeasMain {
    
        public static void main(String[] args) {
            Istart wangfengStar = new WangFengStar();
            Istart proxyObject = (Istart)new ProxyFactory(wangfengStar).getProxyObject();
            proxyObject.sing();
        }
    }

    JDK代理方式不需要代理对象实现接口,但是目标对象一定要实现接口,但是我们在项目中有很多需要代理的类并没有实现接口,所以这也算是这种代理方式的一种缺陷。

    5、cglib动态代理

    如果我们 需要给没有是实现任何接口的目标类生成代理对象,JDK方式是做不到的。这是就可以使用继承目标类以目标对象子类的方式实现代理,这种方法就叫做Cglib代理,也叫做子类代理,他是在内存中构建一个子类对象从而 实现对目标对象功能的扩展。

    Cglib是一个强大的高性能代码生成包,他可以在运行期扩展java类和扩展java接口。它广泛的被许多AOP框架使用,例如Sring AOP和synaop,为他们提供方法的intercepion(拦截)

    Cglib包的底层是通过使用一个小而快的字节码处理框架ASM来转换字节码并生成新的类。

    Cglib子类代理实现方法:

    1.需要引入cglib的jar文件 cglib-2.2.2.jar asm-3.3.1.jar,但是Spring的核心包中已经包括了Cglib功能,所以直接引入spring-core-3.2.5.jar即可.
    2.引入功能包后,就可以在内存中动态构建子类
    3.代理的类不能为final,否则报错
    4.目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法.

    目标类:

    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1410:57
     */
    public class JieLunStar {
    
        public void sing(){
            System.out.println("杰伦唱歌");
        }
    }

    代理工厂:

    import org.springframework.cglib.proxy.Enhancer;
    import org.springframework.cglib.proxy.MethodInterceptor;
    import org.springframework.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    
    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1410:58
     */
    public class CglibProxyFactory implements MethodInterceptor {
    
        //维护目标对象
        private Object target;
    
        public CglibProxyFactory(Object target) {
            this.target = target;
        }
    
        /**
         * @Description:获得目标类的代理对象
         * @author: zhenghao
         * @date: 2020/12/14 11:02
        */
        public Object getProxyObject(){
            //1、工具类
            Enhancer enhancer = new Enhancer();
            //2、设置父类
            enhancer.setSuperclass(target.getClass());
            //3、设置回调
            enhancer.setCallback(this);
            //4、创建代理类
            Object proxyObject = enhancer.create();
            return proxyObject;
    
        }
    
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    
            System.out.println("演唱会前工作");
            //执行目标对象的目标方法
            method.invoke(target,objects);
            System.out.println("演唱后前工作");
            return null;
        }

    测试类:

    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1410:46
     */
    public class CglibTeasMain {
    
        public static void main(String[] args) {
            JieLunStar jieLunStar = new JieLunStar();
            JieLunStar proxyObject = (JieLunStar)new CglibProxyFactory(jieLunStar).getProxyObject();
            proxyObject.sing();
        }
    }
    

    到这三种代理方式我们都介绍完了,下面总结一下:

    1、如果目标对象实现了接口,我们就采用JDK方式实现动态代理

    2、如果目标对象没有实现接口,我们就需要采用cglib方式实现动态代理;

    6、目标是接口+注解的动态代理

    注解类:

    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1411:33
     */
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Select {
    
        String value() default "";
    }

    目标类:

    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1411:32
     */
    public interface IUserDao {
    
        @Select("select * from user")
        String getUser();
    
      
    }
    InvocationHandler类:
    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1410:32
     */
    public class UserInvocationHandler implements InvocationHandler {
    
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //创建类的是一个具体的实现类
            if (Object.class.equals(method.getDeclaringClass())){
                return method.invoke(this,args);
            }else {
                //得到所有注解
                String value = method.getAnnotation(Select.class).value();
                System.out.println("接口上面的注解的内容:" + value);
    
                //实现具体的业务逻辑 如远程http调用实现等
                return "user info";
            }
    
        }
    }
    

    代理工厂:

    import java.lang.reflect.Proxy;
    
    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1411:47
     */
    public class InterfaceProxyFactory  {
    
        private  Class<?> target;
        private UserInvocationHandler userInvocationHandler;
        public InterfaceProxyFactory( Class<?> target) {
            this.target = target;
            this.userInvocationHandler = new UserInvocationHandler();
        }
    
        public Object getProxyObject(){
            return Proxy.newProxyInstance(target.getClassLoader(),new  Class[]{target},userInvocationHandler);
        }
    }

    测试类:

    /**
     * @author zhenghao
     * @description:
     * @date 2020/12/1410:46
     */
    public class InterfaceProxyTeasMain {
    
        public static void main(String[] args) {
            IUserDao proxyObject = (IUserDao) new InterfaceProxyFactory(IUserDao.class).getProxyObject();
            System.out.println(proxyObject.getUser());
        }
    }

     

    展开全文
  • java 动态代理

    2017-08-29 22:47:38
    java 动态代理deno
  • Java动态代理

    千次阅读 2014-09-29 07:40:40
    Java动态代理是Java语言世界的动态代理。 为了更好地理解动态代理,我们先讲述一下代理模式。 代理模式一种软件设计模式, 是代理类与委托类有同样的接口。代理类主要负责为委托类预处理消息、过滤消息、把消息转发...

     

    动态代理是代理模式的实现,在程序运行时,运用反射机制动态创建而成。Java动态代理是Java语言世界的动态代理。

    为了更好地理解动态代理,我们先讲述一下代理模式。

    代理模式一种软件设计模式, 是代理类与委托类有同样的接口。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。

    如下面代理模式比较通用的类图,Proxy是代理类,RealSubject是目标类,它们实现了同样的接口。也就是说Proxy类可以用在RealSubject使用的地方。

     image_thumb3

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

    Java动态代理的两种实现:JDK动态代理和CGLib动态代理

    • JDK 动态代理

    JDK动态代理是Java 原生的动态代理方法,不需要依赖任何第三方库。通过java.lang.reflect.Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)方法来动态生成代理类。该方法有三个参数:
           loader: 加载代理类的ClassLoader
           interfaces: 代理类代理的目标类的接口
           h:代理类的拦截器,通过定义实现InvocationHandler接口的类来实现自己的拦截器。

    生成的代理类,类名如$ProxyXXX。如下面类图, 代理类$ProxyXXX继承java.lang.reflect.Proxy,并实现一个或者多个目标类的接口。在java.lang.reflect.Proxy类中有一个InvocationHandler类型的属性h,表示用户定义的拦截器。MyInvocationHandler是我们自定义的一个拦截器,其中有一个myTargetObject属性表示目标对象(这个不是必须的,但如果需要代理对象,我们可以将代理对象放在这),还有一个invoke方法,该方法是覆盖了接口中的invoke方法,当调用代理类的方法时,会调用拦截器的invoke方法。
         

    Main_thumb1

    • CGLib 动态代理

    CGLib 动态代理是通过使用一个小而快的字节处理框架ASM(Java字节码操控框架)来转换字节码并生成动态代理需要的类。CGLib除了生成我们需要的代理类,还会生成一些辅助类。

    生成的代理图如下面类图,ObjectClass是我们的目标类,ObjectClass$$EhanceByCGLib$$****是动态生成的代理类,其中有CGLib$CALLBACK_X属性是拦截器。MyMethodInterceptor是我们自己实现的拦截器,其中有一个targetObject属性是代理的目标对象(这个不是必须的,但如果需要代理对象,我们可以将代理对象放在这)。而intercept方法是覆盖的MethodIntercepter的方法, 当调用代理类的方法时,会调用拦截器的intercept 方法。

    ClassDiagram1_thumb2

    展开全文
  • Java 动态代理

    万次阅读 2019-12-09 18:14:20
    Java代理java代理:在不用修改源码的情况下,可以在实现类方法的前后做些额外的处理。 1)、静态代理。 在程序运行前,代理类的.class文件已存在。事先知道要代理的实现类是什么。 优点:不需要知道委托类...

    1、介绍。

    Java代理。

            java代理:在不用修改源码的情况下,可以在实现类方法的前后做些额外的处理。

      1)、静态代理。

            在程序运行前,代理类的.class文件已存在。事先知道要代理的实现类是什么。

            优点:不需要知道委托类(实现类),只需知道代理类即可。

            缺点:(1)代码重复。代理类和委托类(实现类)实现了相同的接口。
                       (2)维护复杂。接口增加一个方法,所有的代理类和委托类(实现类)都需要实现此方法,而且代理类和委托类(实现类)的关系为一对一,无法一对多。

      2)、动态代理。

            在程序运行时,通过反射机制动态生成代理类。事先不知道要代理的实现类是什么。

            优点:(1)能代理该接口的所有实现类。

                       (2)接口中的所有方法都在InvocationHandler.invoke方法中统一处理,不像静态代理那样每个都进行处理。        缺点:Java动态代理只能代理接口,要代理类需要使用如cglib第三方的类库。

     

    2、代码。Proxy.java、DynamicProxy.java、UserServiceImpl.java、IUserService.java、User.java。

    package com.zxj.test.proxy;
    
    import c
    展开全文
  • JAVA动态代理

    千次阅读 2014-05-15 13:23:56
    JAVA动态代理 代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会...

    JAVA的动态代理
    代理模式
    代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。 
    按照代理的创建时期,代理类可以分为两种。 
    静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。 
    动态代理:在程序运行时,运用反射机制动态创建而成。 

    首先看一下静态代理:

    1Count.java:

     

    package net.battier.dao;    
    /** 
      * 定义一个账户接口 
      *  
      * @author Administrator 
      *  
      */  
      public interface Count {  
      // 查看账户方法  
      public void queryCount();  
      // 修改账户方法  
      public void updateCount();  
    }  
    
    2.CountImpl.java 

     

    package net.battier.dao.impl;  
      
    import net.battier.dao.Count;  
      
    /** 
     * 委托类(包含业务逻辑) 
     *  
     * @author Administrator 
     *  
     */  
    public class CountImpl implements Count {  
      
        @Override  
        public void queryCount() {  
            System.out.println("查看账户方法...");  
      
        }  
      
        @Override  
        public void updateCount() {  
            System.out.println("修改账户方法...");  
      
        }  
      
    }  
    
    3.CountProxy.java

    package net.battier.dao.impl;  
      
    import net.battier.dao.Count;  
      
    /** 
     * 这是一个代理类(增强CountImpl实现类) 
     *  
     * @author Administrator 
     *  
     */  
    public class CountProxy implements Count {  
        private CountImpl countImpl;  
      
        /** 
         * 覆盖默认构造器 
         *  
         * @param countImpl 
         */  
        public CountProxy(CountImpl countImpl) {  
            this.countImpl = countImpl;  
        }  
      
        @Override  
        public void queryCount() {  
            System.out.println("事务处理之前");  
            // 调用委托类的方法;  
            countImpl.queryCount();  
            System.out.println("事务处理之后");  
        }  
      
        @Override  
        public void updateCount() {  
            System.out.println("事务处理之前");  
            // 调用委托类的方法;  
            countImpl.updateCount();  
            System.out.println("事务处理之后");  
      
        }  
      
    }  

    4. TestCount.java 

    package net.battier.test;  
      
    import net.battier.dao.impl.CountImpl;  
    import net.battier.dao.impl.CountProxy;  
      
    /** 
     *测试Count类 
     *  
     * @author Administrator 
     *  
     */  
    public class TestCount {  
        public static void main(String[] args) {  
            CountImpl countImpl = new CountImpl();  
            CountProxy countProxy = new CountProxy(countImpl);  
            countProxy.updateCount();  
            countProxy.queryCount();  
      
        }  
    }  
    观察代码可以发现每一个代理类只能为一个接口服务,这样一来程序开发中必然会产生过多的代理,而且,所有的代理操作除了调用的方法不一样之外,其他的操作都一样,则此时肯定是重复代码。解决这一问题最好的做法是可以通过一个代理类完成全部的代理功能,那么此时就必须使用动态代理完成。 


    再来看一下动态代理: 

    与静态代理类的创建不同的是生成代理的方式,这里使用了java.lang.reflect.Proxy类的newProxyInstance()方法生成一个代理,并且在生成过程中需要传入一个代理处理器,java.lang.reflect.InvocationHandler的一个实现类。

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

    其中生成的代理类是由Java内部执行的。

    Java动态代理涉及到的类:
    public interface InvocationHandler
        InvocationHandler 是代理实例的调用处理程序 实现的接口。 
    
    每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法。
    invoke
    Object invoke(Object proxy,
                  Method method,
                  Object[] args)
                  throws Throwable在代理实例上处理方法调用并返回结果。在与方法关联的代理实例上调用方法时,将在调用处理程序上调用此方法。 
    
    参数:
    proxy - 在其上调用方法的代理实例
    method - 对应于在代理实例上调用的接口方法的 Method 实例。Method 对象的声明类将是在其中声明方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。
    args - 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null。基本类型的参数被包装在适当基本包装器类(如 java.lang.Integer 或 java.lang.Boolean)的实例中。 
    返回:
    从代理实例的方法调用返回的值。如果接口方法的声明返回类型是基本类型,则此方法返回的值一定是相应基本包装对象类的实例;否则,它一定是可分配到声明返回类型的类型。如果此方法返回的值为 null 并且接口方法的返回类型是基本类型,则代理实例上的方法调用将抛出 NullPointerException。否则,如果此方法返回的值与上述接口方法的声明返回类型不兼容,则代理实例上的方法调用将抛出 ClassCastException。 
    抛出: 
    Throwable - 从代理实例上的方法调用抛出的异常。该异常的类型必须可以分配到在接口方法的 throws 子句中声明的任一异常类型或未经检查的异常类型 java.lang.RuntimeException 或 java.lang.Error。如果此方法抛出经过检查的异常,该异常不可分配到在接口方法的 throws 子句中声明的任一异常类型,代理实例的方法调用将抛出包含此方法曾抛出的异常的 UndeclaredThrowableException。
    public class Proxy
        extends Object
        implements Serializable
        Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。
    Proxy
    protected Proxy(InvocationHandler h)使用其调用处理程序的指定值从子类(通常为动态代理类)构建新的 Proxy 实例。 
    
    参数:
    h - 此代理实例的调用处理程序
    getProxyClass
    public static Class<?> getProxyClass(ClassLoader loader,
                                         Class<?>... interfaces)
                                  throws IllegalArgumentException返回代理类的 java.lang.Class 对象,并向其提供类加载器和接口数组。该代理类将由指定的类加载器定义,并将实现提供的所有接口。如果类加载器已经定义了具有相同排列接口的代理类,那么现有的代理类将被返回;否则,类加载器将动态生成并定义这些接口的代理类。 
    对可以传递给 Proxy.getProxyClass 的参数有以下几个限制: 
    
    interfaces 数组中的所有 Class 对象必须表示接口,而不能表示类或基本类型。 
    interfaces 数组中的两个元素不能引用同一 Class 对象。 
    所有接口类型的名称通过特定的类加载器必须可见。换句话说,对于类加载器 cl 和所有接口 i,以下表达式必须为 true: 
         Class.forName(i.getName(), false, cl) == i
     所有非公共接口必须位于同一包中;否则,该代理类将不可能实现所有的接口,无论它在哪一个包中定义。 
    对于有相同签名的指定接口中任何成员方法集: 
    如果任何方法的返回类型是基本类型或 void,那么所有的方法必须具有与此相同的返回类型。 
    否则,该方法之一必须是返回类型,它可以指派给该方法其余的所有返回类型。 
    得到的代理类必须不超过虚拟机在类上施加的任何限制。例如,虚拟机可以限制某一类实现至多 65535 的接口数;在这种情况下,interfaces 数组的大小必须不超过 65535。 
    如果违反了这些限制,Proxy.getProxyClass 将抛出 IllegalArgumentException。如果 interfaces 数组参数或其任何元素为 null,则将抛出 NullPointerException。 
    
    注意,指定的代理接口的顺序非常重要:对接口组合相同但顺序不同的代理类的两个请求会导致两个不同的代理类。 
    
    参数:
    loader - 定义代理类的类加载器
    interfaces - 代理类要实现的接口列表 
    返回:
    用指定的类加载器定义的代理类,它可以实现指定的接口 
    抛出: 
    IllegalArgumentException - 如果违反传递到 getProxyClass 的参数上的任何限制 
    NullPointerException - 如果 interfaces 数组参数或其任何元素为 null
    newProxyInstance
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
                                   throws IllegalArgumentException返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。此方法相当于: 
         Proxy.getProxyClass(loader, interfaces).
             getConstructor(new Class[] { InvocationHandler.class }).
             newInstance(new Object[] { handler });
     Proxy.newProxyInstance 抛出 IllegalArgumentException,原因与 Proxy.getProxyClass 相同。 
    
    参数:
    loader - 定义代理类的类加载器
    interfaces - 代理类要实现的接口列表
    h - 指派方法调用的调用处理程序 
    返回:
    一个带有代理类的指定调用处理程序的代理实例,它由指定的类加载器定义,并实现指定的接口 
    抛出: 
    IllegalArgumentException - 如果违反传递到 getProxyClass 的参数上的任何限制 
    NullPointerException - 如果 interfaces 数组参数或其任何元素为 null,或如果调用处理程序 h 为 null
    isProxyClass
    public static boolean isProxyClass(Class<?> cl)当且仅当指定的类通过 getProxyClass 方法或 newProxyInstance 方法动态生成为代理类时,返回 true。 
    此方法的可靠性对于使用它做出安全决策而言非常重要,所以此方法的实现不应仅测试相关的类是否可以扩展 Proxy。 
    
    参数:
    cl - 要测试的类 
    返回:
    如该类为代理类,则为 true,否则为 false 
    抛出: 
    NullPointerException - 如果 cl 为 null
    getInvocationHandler
    public static InvocationHandler getInvocationHandler(Object proxy)
                                                  throws IllegalArgumentException返回指定代理实例的调用处理程序。 
    
    参数:
    proxy - 返回调用处理程序的代理实例 
    返回:
    代理实例的调用处理程序 
    抛出: 
    IllegalArgumentException - 如果参数不是一个代理实例

    动态代理类:在运行时生成的class,在其生成过程中,你必须提供一组接口给它,然后该class就声称实现了这些接口。可以把该class的实例当做这些接口中的任何一个来用。其实,这个Dynamic Proxy就是一个Proxy,他不会替你做任何实质性的工作。在生成它的实例时,必须提供一个Handler,由它接管实际的工作。

    在使用动态代理类时,必须实现InvocationHandler接口。

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

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

    动态代理示例:

    1.BookFacade.java

    package net.battier.dao;  
      
    public interface BookFacade {  
        public void addBook();  
    }  
    2.BookFacadeImpl.java

    package net.battier.dao.impl;  
      
    import net.battier.dao.BookFacade;  
      
    public class BookFacadeImpl implements BookFacade {  
      
        @Override  
        public void addBook() {  
            System.out.println("增加图书方法。。。");  
        }  
      
    }  


    3.BookFacadeProxy.java

    package net.battier.proxy;  
      
    import java.lang.reflect.InvocationHandler;  
    import java.lang.reflect.Method;  
    import java.lang.reflect.Proxy;  
      
    /** 
     * JDK动态代理代理类 
     *  
     * @author student 
     *  
     */  
    public class BookFacadeProxy implements InvocationHandler {  
        private Object target;  
        /** 
         * 绑定委托对象并返回一个代理类 
         * @param target 
         * @return 
         */  
        public Object bind(Object target) {  
            this.target = target;  
            //取得代理对象  
            return Proxy.newProxyInstance(target.getClass().getClassLoader(),  
                    target.getClass().getInterfaces(), this);   //要绑定接口
        }  
      
        @Override  
        /** 
         * 调用方法 
         */  
        public Object invoke(Object proxy, Method method, Object[] args)  
                throws Throwable {  
            Object result=null;  
            System.out.println("事物开始");  
            //执行方法  
            result=method.invoke(target, args);  
            System.out.println("事物结束");  
            return result;  
        }  
      
    }  

    4. TestProxy.java 

    package net.battier.test;  
      
    import net.battier.dao.BookFacade;  
    import net.battier.dao.impl.BookFacadeImpl;  
    import net.battier.proxy.BookFacadeProxy;  
      
    public class TestProxy {  
      
        public static void main(String[] args) {  
            BookFacadeProxy proxy = new BookFacadeProxy();  
            BookFacade bookProxy = (BookFacade) proxy.bind(new BookFacadeImpl());  
            bookProxy.addBook();  
        }  
      
    }  
    看完上面的代码,大致明白动态代理的含义: 
    A接口有c方法,类B实现A接口,原本应该是执行B类中的c方法,可现在不这样做; 
    我声明产生B类的代理类B',由它来冒充B类的“兄弟”并“实现”A接口, 
    对外界来说B'应该也有c方法,可当真正调用它的时候, 
    它会去执行与它关联InvocationHandler的invoke()方法, 
    在这个方法里面你可以做很多事情。这样,这个请求就被“代理”到其它地方去了。

    展开全文
  • 本文通过分析Java动态代理的机制和特点,解读动态代理类的源代码,并且模拟推演了动态代理类的可能实现,向读者阐述了一个完整的 Java动态代理运作过程,希望能帮助读者加深对Java动态代理的理解和应用。本文的标签...
  • java动态代理详解

    万次阅读 多人点赞 2018-08-21 15:32:51
    目前java动态代理的实现分为两种 1.基于JDK的动态代理 2.基于CGILB的动态代理 在业务中使用动态代理,一般是为了给需要实现的方法添加预处理或者添加后续操作,但是不干预实现类的正常业务,把一些基本业务和主要...
  • java动态代理demo

    2016-03-15 14:57:11
    适用于初探java动态代理模式,精简易懂。
  • java动态代理例子

    2013-11-27 22:57:32
    java动态代理例子,这里面有两个例子,一个是jdk的动态代理,一个是cglib的动态代理,让你明白什么是动态代理,动态代理可以做什么。
  • java动态代理.rar

    2018-04-13 14:19:17
    java动态代理项目源代码以及*.class文件反汇编工具,可以下载学习
  • java 动态代理 完整版

    2010-11-29 09:43:12
    java动态代理 完整版 java动态代理 完整版 java动态代理 完整版 java动态代理 完整版 java动态代理 完整版
  • java学习——Java 动态代理机制分析

    千次阅读 2017-04-12 16:53:50
    越学越觉得自己不懂的越多!java的动态代理学习资料整理:Java 动态代理机制分析及扩展,第 1 部分: ...https://www.zhihu.com/question/20794107Java动态代理机制详解(JDK 和CGLIB,Javassist,A
  • Java动态代理和Java反射的Demo演示,通俗易懂。
  • Java动态代理机制详解_动力节点Java学院整理,动力节点口口相传的Java黄埔军校
  • 自己总结的代理模式和Java中的动态代理模式,有源码
  • Java动态代理helloworld

    2013-08-18 23:53:16
    Java动态代理的helloworld,抛砖引玉吧

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 264,297
精华内容 105,718
关键字:

java的动态代理

java 订阅