实例讲解Java中动态代理和反射机制

 更新时间:2019年01月24日 14:19:37   投稿:laozhang  
在本篇文章里小编给各位分享了关于Java中动态代理和反射机制的相关知识点内容,有需要的朋友们学习下。

反射机制

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

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

静态代理

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

动态代理

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

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

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

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

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

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

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

动态代理的代理类是在静态代理类上进行修改,将动态代理类实现InvocationHandler接口,JAVA电子书重写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就可以直接定位要调用的方法,并直接进行调用。这样省去了反射调用,所以效率高。

相关文章

  • Spring中Bean的三种实例化方式详解

    Spring中Bean的三种实例化方式详解

    这篇文章主要给大家介绍了关于Spring中实例化bean的三种方式:构造方法、静态工厂和实例工厂,对我们学习有一定的参考价值,需要的小伙伴可以了解一下
    2022-06-06
  • Mybatis分页插件PageHelper的使用详解

    Mybatis分页插件PageHelper的使用详解

    这篇文章主要介绍了Mybatis分页插件PageHelper的相关资料,该插件目前支持Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL六种数据库分页需要的朋友可以参考下
    2016-12-12
  • java实现打砖块游戏算法

    java实现打砖块游戏算法

    这篇文章主要为大家详细介绍了java实现打砖块游戏算法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-05-05
  • SpringBoot2零基础到精通之JUnit 5与指标监控

    SpringBoot2零基础到精通之JUnit 5与指标监控

    SpringBoot是一种整合Spring技术栈的方式(或者说是框架),同时也是简化Spring的一种快速开发的脚手架,本篇让我们一起学习JUnit 5与指标监控
    2022-03-03
  • java实现html转pdf方法步骤

    java实现html转pdf方法步骤

    这篇文章主要给大家介绍了关于java实现html转pdf方法的相关资料,要将HTML转换成PDF,我们需要借助Java中的第三方库,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2023-08-08
  • Spring Security放行的接口Knife4j静态资源的问题小结

    Spring Security放行的接口Knife4j静态资源的问题小结

    这篇文章主要介绍了Spring Security使用Knife4j静态资源的问题小结,项目中使用 Spring Security 做身份认证和授权,使用 Knife4j 做接口调试,需要 Spring Security 放行的接口记录在 RequestMatcherConstant 类中,感兴趣的朋友跟随小编一起看看吧
    2024-02-02
  • SpringBoot项目如何打可执行war包

    SpringBoot项目如何打可执行war包

    最近小编做了一个springboot项目,最后需要打成war包在容器中部署,下面小编给大家分享下SpringBoot项目如何打可执行war包,感兴趣的朋友一起看看吧
    2020-04-04
  • Java中Math类常用方法代码详解

    Java中Math类常用方法代码详解

    本文是小编最新给大家整理的关于Java中Math类常用方法的知识,通过实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧
    2017-07-07
  • 浅谈maven单元测试设置代理

    浅谈maven单元测试设置代理

    下面小编就为大家带来一篇浅谈maven单元测试设置代理。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • Redisson分布式锁的原理和代码实例

    Redisson分布式锁的原理和代码实例

    这篇文章主要介绍了Redisson分布式锁的原理和代码实例,在分布式系统中,锁机制是非常重要的,Redisson是一个基于Redis的Java应用程序,常常被应用作为分布式锁的解决方案,需要的朋友可以参考下
    2024-01-01

最新评论