实例讲解Java中 * 和反射机制
作者:laozhang 发布时间:2022-06-29 04:00:50
反射机制
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就可以直接定位要调用的方法,并直接进行调用。这样省去了反射调用,所以效率高。


猜你喜欢
- 桶排序桶排序是计数排序的升级,计数排序可以看成每个桶只存储相同元素,而桶排序每个桶存储一定范围的元素,通过函数的某种映射关系,将待排序数组中
- 引言在实际应用场景中,我们封装一个学生的类,这个类用于封装学生的日常行为,如:上学、吃饭、上课等。然而,在疫情期间,学生上学时入校、吃饭时进
- 使用mybatis-plus自动生成了5个模块(xml/bean/mapper/service/controller)的代码,这里练习一下m
- 简述Java中Socket分为普通Socket和NioSocket两种,这里介绍Socket。我们可以把Socket比作两个城市间的交通工具
- 从配置获取的配置默认是明文的,有些像数据源这样的配置需要加密的话,需要对配置中心进行加密处理。下面使用对称性加密来加密配置,需要配置一个密钥
- 引言本文我们来分析NameServer相关代码,在正式分析源码前,我们先来回忆下NameServer的功能:NameServer是一个非常简
- Android ListView仿聊天界面效果图的具体代码,供大家参考,具体内容如下1.首先页面总布局(ListView + LinearL
- package list;import java.util.ArrayList;/** * Java约瑟夫问题: n个人(不同id
- Controller如何进行重定向Spring MVC中进行重定向本人知道的有两种方式方法返回的URI(相对路径)中加上"redi
- 1.Fragment概述在一个Activity中, Fragment代表UI的一个部分或者一个行为。一个Activity可以结合多个Frag
- 上代码dialog.getWindow().getDecorView().setSystemUiVisibility(View.
- 有时候我们需要实现这样的场景,类似进入开发者模式,即多次点击后执行操作。首先我们先看一个方法:System提供的一个静态方法arraycop
- 身为程序员我们对线程是再熟悉不过了,多线程并发算是Java进阶的知识,用好多线程不容易有太多的坑。创建线程也算是一个"重"
- 前言C#基于NAudio工具对Wav音频文件进行剪切,将一个音频文件剪切成多个音频文件注:调用方法前需要导入NAudio.dll或者在NuG
- 干Java这么久,一直在做WEB相关的项目,一些基础类差不多都已经忘记。经常想得捡起,但总是因为一些原因,不能如愿。其实不是没有时间,只是有
- 第一个方法是计算出阶乘然后计算字符串的0的个数。import java.util.Scanner;import java.math.BigD
- 1,刚刚在别人开源的项目中看到了一个挺不错的用户体验,效果图如下:2,那下面我们就来实现一下,首先看一下布局,由于一般只是我们包含头像的那部
- 什么是Drawable首先Drawable是一个抽象类,表示的是可以在Canvas中绘制的图像,常被用作一个view的背景,有多种实现类完成
- 记录窗口上次关闭的位置和大小namespace PDSafe.Base{ public class Se
- 智能终端上的游戏目前风头正劲,试问哪个智能手机上没有几款企鹅公司出品的游戏呢!之前从未涉猎过游戏开发,但知道游戏开发前要挑选一款合适的游戏引