zoukankan      html  css  js  c++  java
  • Java动态代理和反射机制

      反射机制

        Java语言提供的一种基础功能,通过反射,我们可以操作这个类或对象,比如获取这个类中的方法、属性和构造方法等。

      动态代理:分为JDK动态代理、cglib动态代理(spring中的动态代理)。

        静态代理

          预先(编译期间)确定了代理者与被代理者之间的关系,也就是说,若代理类在程序运行前就已经存在了,这种情况就叫静态代理

        动态代理

          代理类在程序运行时创建的代理方式。也就是说,代理类并不是在Java代码中定义的,而是在运行期间根据我们在Java代码中的“指示”动态生成的。

      动态代理比静态代理的优势在于:

        动态代理可以很方便的对代理类的函数进行统一的处理(invoke),而不是修改每个代理类的函数,更灵活和扩展。

      JDK的动态代理(依赖于接口

        在Java的动态代理机制中,有两个重要的类或接口,一个是InvocationHandler接口,另一个是Proxy类。

        InvocationHandler接口是给动态代理类实现的,负责处理被代理对象的操作

        Proxy类是用来创建动态代理类实例对象的,只有得到这个对象,才能调用需要代理的方法。

             动态代理的代理类是在静态代理类上进行修改,将动态代理类实现InvocationHandler接口,重写Invoke方法,Invoke方法通过传入的被代理类方法和参数来执行。

        如下实例:

    public interface AppService {
    	void createApp(String name);
    	void deleteApp(String name);
    }
    
    //代理类(比如微商代理)
    public class AppServiceImpl implements AppService{
    
    	@Override
    	public void createApp(String name) {
    		System.out.print("App["+name+"] has been created.");
    	}
    
    	@Override
    	public void deleteApp(String name) {
    		System.out.print("App["+name+"] has been delete.");
    	}
    }
    
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    public class LoggerInterceptor implements InvocationHandler {
        private Object target; //委托类(被代理类)的实例,比如厂家
        public LoggerInterceptor(Object target){  
            this.target = target;  
        }  
    	@Override
    	public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
    		System.out.println("Entered "+target.getClass().getName()+"-"+method.getName()+",with arguments{"+args[0]+"}");  
            Object result = method.invoke(target, args);
           //调用目标对象的方法  (调用厂家的方法(createApp)及参数(Kevin Test))
            System.out.println("Before return:"+result);  
            return result;  
    	}
    
    }

      

    import java.lang.reflect.Proxy;
    
    public class test {
    
    public static void main(String[] args) {
        AppService target = new AppServiceImpl();//生成目标对象 (代理类的对象)
        //接下来创建代理对象 
        AppService proxy = (AppService) Proxy.newProxyInstance( 
        target.getClass().getClassLoader(), 
        target.getClass().getInterfaces(), new LoggerInterceptor(target)); 
        proxy.createApp("Kevin Test1"); 
        proxy.deleteApp("Kevin Test2"); 
      }
    
    }
    
    /**
    * 1、jdk的动态代理实现方式是依赖于接口的,首先使用接口来定义好操作规范。
    * 2、通过proxy类产生的代理对象调用被代理对象的操作。
    * 3、而这个操作又被分发给InvocationHandler接口的invoke方法具体执行
    * 
    * 在java的动态代理机制中,有两个重要的类或接口,一个是InvocationHandler接口、另一个则是 Proxy类,这个类和接口是实现我们动态代理所必须用到的。
    InvocationHandler接口是给动态代理类实现的,负责处理被代理对象的操作的,而Proxy是用来创建动态代理类实例对象的,因为只有得到了这个对象我们才能调用那些需要代理的方法。
    * 
    * 此方法的参数含义如下 
    proxy:代表动态代理对象 
    method:代表正在执行的方法 
    args:代表当前执行方法传入的实参 
    返回值:表示当前执行方法的返回值
    * 
    * 如上:
    * 使用了Proxy类的newProxyInstance方法生成代理对象,然后用这个对象去调用createApp()和deleteApp()方法,
    * 其实系统会将这2个方法分发给invoke()方法区执行。其中proxy对象的类是系统帮我们动态创建了,其实实现了我们的业务接口AppService
    * 
    */
    

      

      cglib动态代理(继承方式

      cglib动态代理中使用MethodInterceptor来实现动态代理类。

      拦截器MethodInterceptor中就是由MethodProxy的InvokSuper方法调用代理方法的。

      MethodProxy类生成代理方法和代理方法的签名。

      JDK动态代理和Cglib动态代理的区别:

      1、JDK动态代理是实现了被代理对象的接口,Cglib是继承了被代理对象。

      2、Cglib因为是继承机制,所以无法代理被final修饰的方法。

      3、JDK和Cglib都是在运行期间生产字节码,JDK是直接写class字节码,Cglib使用ASM框架写class字节码;cglib代理实现更复杂,生成代理类比JDK效率低。

      4、JDK调用代理方法,是通过反射实现机制调用,cglib是通过Fashclass机制直接调用方法,效率更高。

      Fastcalss机制:

        为代理类和被代理类个生成一个class,这个class会为代理类或被代理类的方法分配一个index。

        这个index当做一个入参,Fashclass就可以直接定位要调用的方法,并直接进行调用。这样省去了反射调用,所以效率高。

  • 相关阅读:
    EasyFlash 的初始化配置
    不能靠眼睛之 KEIL 中失效代码灰暗特性
    C 头文件、宏、编译问题
    C++ 中 const、volatile、mutable的用法
    【转】C++ const 关键字总结
    你想要的成都全攻略,好耍不重样——成都胖娃呕心巨作
    【转】RO段、RW段和ZI段 --Image$$??$$Limit 含义(zz)
    深有体会内存对系统性能的重要性
    毕业论文编写笔记
    (二)基于商品属性的相似商品推荐算法——Flink SQL实时计算实现商品的隐式评分
  • 原文地址:https://www.cnblogs.com/MoreThinking/p/10310251.html
Copyright © 2011-2022 走看看