b04-2 spring容器相关java知识-反射(精通Spring 4.x)

本篇内容:

  • 1、java反射实现
  • 2、java类加载器ClassLoader
  • 3、java反射机制

一、java反射代码

1、创建java实体类

public class Car {
    private String brand;
    private String color;
    private int maxSpeed;
    public Car() {
    }
    public Car(String brand, String color, int maxSpeed) {
        this.brand = brand;
        this.color = color;
        this.maxSpeed = maxSpeed;
    }
    public void getData() {
        System.out.println("Car{" +
                "brand='" + brand + '\'' +
                ", color='" + color + '\'' +
                ", maxSpeed=" + maxSpeed +
                '}');
    }
    //    省略get,set方法
}

2、测试类:通过反射获取java对象

public class CarTest {
    public static Car initByDefaultConst() throws Exception {
        //得到ClassLoader对象
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        //通过java全路径名称获取java实体对象
        Class aClass = loader.loadClass("com.demo.Car");
        //获取反射对
        Constructor constructor = aClass.getDeclaredConstructor(null);
        //通过构造函数实例化java对象
        Car car = (Car) constructor.newInstance();
        //通过类对象获取实体的setter方法
        Method setBrand = aClass.getMethod("setBrand", String.class);
        setBrand.invoke(car, "雷克萨斯 ES");
        Method setColor = aClass.getMethod("setColor", String.class);
        setColor.invoke(car, "银色");
        Method setMaxSpeed = aClass.getMethod("setMaxSpeed", int.class);
        setMaxSpeed.invoke(car, 300);
        return car;
    }
    @Test
    public void getCar() throws Exception {
        Car car = initByDefaultConst();
        car.getData();
    }
}

二、java的类加载器ClassLoader

1、工作机制

  • 寻找类的字节码文件并构造出类在JVM内部表示对象的组件。

类加载器把一个类加入jvm的步骤

  • 1、装载:查找和导入Class文件

  • 2、连接:执行校验、准备和解析步骤(解析步骤是可选的)

  • 2.1、校验:检查载入Class文件数据的准确性

  • 2.2、准备:给类的静态变量分配存储空间

  • 2.3、解析:将符号引用转换成直接引用

  • 3、初始化:对类的静态变量,静态代码块执行初始化工作

  • 类的装载构造由ClassLoader及其子类负责,ClassLoader是一个重要的java运行时系统组件,负责在运行时查找和装入class字节码文件

  • JVM在运行时会产生3个ClassLoader:根装载器,ExtClassLoader(扩展类装载器),APPClassLoader(应用类装载器)

2、测试jvm中3个类的关系

    @Test
    public void getJVM(){
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        System.out.println("current: "+loader);
        System.out.println("current: "+loader.getParent());
        System.out.println("current: "+loader.getParent().getParent());
    }
    
  • 输出
current: sun.misc.Launcher$AppClassLoader@18b4aac2
current: sun.misc.Launcher$ExtClassLoader@776ec8df
current: null
  • 从输出内容可知:
  • 1、ClassLoader就是AppClassLoader,
  • 2、ClassLoader的父类是ExtClassLoader

jvm装载类时使用“全盘负责委托机制”。

  • 1、“全盘负责”:是指当一个ClassLoader装载一个类时,除非显示地使用另一个ClassLoader,该类所依赖及引用的类也由这个类载入。
  • 2、“委托机制”:是指先委托父类装载器找目标类,只有在找不到的情况下才从自己的类路径中查找并装载目标。

3、ClassLoader的重要方法

1、Class loadClass(String name)

  • name参数指定类装载需要的类名,必须使用全路径名称。重载方法Class loadClass(String name,boolean resolve)resolve参数告诉类装载器是否需要解析该类,在初始化前要考虑进行解析的工作,单不是所有的类都需要解析。

2、Class defuneClass(String name, byte[ ] b, int off, int len)

  • 将类文件的字节数组转换成JVM内部的Class对象,字节数组可以从本地文件系统,远程网络获取。参数name为全路径类名。

3、Class findSystemClass(String name)

  • 将本地文件系统载入Class文件,如果本地文件不存在该Class文件,将抛出ClassNotFoundException,该方法是JVM默认使用的装载机制

4、ClassLoader getParent()

  • 获取父类装载器,处理根装载器外所有的类装载器只有一个父装载器。ExtClassLoader的父装载器是根装载器,因为跟装载器不是java语言编写,无法获取
每个类在JVM中都拥有一个对应的Class对象,它提供了类结构信息的描述。Class对象是在装载类时由JVM通过调用类装载器中的defineClass()自动构造。

三、java反射机制

  • Class反射对象描述类语义结构,可以从Class对象中获取构造函数,成员变量,方法类等元素的反射对象,并以编程的方式通过这些反射对象对目标进行操作。
  • java主要反射类:Constructor,Method,Field

1、Constructor: 类的构造函数反射类

  • 通过Class#getConstructor()可以获取类的所有构造函数反射对象数组。
  • Constructor的一个主要方法是newInstance(Object[ ] initargs),通过此方法可以创建一个对象类的实例

2、Method:类方法的反射类

  • 通过Class#getDecrlaredMethods()可以获取类的所有方法反射类对象数组Method[ ]。
  • Method最主要的方法是incoke(Object obj,Object[ ] args),obj表示操作的目标对象,args为方法参数

Method用于获取类信息方法

  • Class getReturnType():获取方法的返回值类型
  • Class[ ] getParameterTypes():获取方法入参类型数组
  • Class[ ] getExceptionType():获取方法异常类型数组
  • Annotation[ ] [ ] getParameterAnnotations():获取方法的注解信息

3、Field:类的成员变量的反射类

  • 通过Class#getDeclaredFields()可以获取类的成员变量反射对象数组。
  • Class#getDeclaredField(String name):可以获取某个特定名称的成员变量反射对象
  • 主要方法:set(Object obj,Object value),obj表示操作的目标对象,value为设置值
  • 如果成员变量为基础类型,可以使用Fiel提供的带类型名的值设置方法:setBoolean(Object obj,boolean value),setInt(Object obj,int value)

4、私有方法反射

  • java为包提供了Package反射类,有注解反射类:AnnotatedElement反射类。
  • java的反射体系保证了可以通过程序化的方式访问目标类中所有的元素,对private或protected成员变量和方法,只要JVM安全机制允许也可以通过反射调用

4.1、定义实体类

public class PrivateCar {
    private String color;
    protected void getData() {
        System.out.println("the color is :" + color);
    }
}

4.2、测试类

public class PrivateCarTest {
    @Test
    public void getCar() throws Exception {
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        Class clazz = loader.loadClass("com.demo.PrivateCar");
        PrivateCar car = (PrivateCar) clazz.newInstance();
        Field colorField = clazz.getDeclaredField("color");
        colorField.setAccessible(true);     //取消java语言访问检查
        colorField.set(car,"银色");
        Method method = clazz.getDeclaredMethod("getData", null);
        method.setAccessible(true);     //取消java语言访问检查
        method.invoke(car,null);
    }
}

注意:

  • 访问private或protected修饰的对象或方法需要调用setAccessible(boolean access)取消java语言检查,否则抛出异常。

demo代码地址


https://github.com/brusion/brusion-code/tree/master/demo-java/03%20-%20demo%20-%20spring/spring-study-4x/01-ioc/01-ioc-java

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容

  • (一)Java部分 1、列举出JAVA中6个比较常用的包【天威诚信面试题】 【参考答案】 java.lang;ja...
    独云阅读 7,101评论 0 62
  • 1 基本信息 每个开发人员对java.lang.ClassNotFoundExcetpion这个异常肯定都不陌生,...
    java小菜鸟阅读 2,608评论 0 15
  • ClassLoader翻译过来就是类加载器,普通的java开发者其实用到的不多,但对于某些框架开发者来说却非常常见...
    时待吾阅读 1,073评论 0 1
  • Summer篇 Summer与冬华分手后,回到了自己的家乡。离开了冬华的Summer仿佛像鱼儿离开了水一样,无法生...
    紫晨樱逝阅读 216评论 4 4
  • 科大是美丽的学府、也是安徽合肥的骄傲!里面的牛人更不必说!我也是对此向往已久、连来他们这里面试和上个课都激动、!走...
    lawyer丽阅读 140评论 0 1