IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 框架的灵魂------反射 -> 正文阅读

[Java知识库]框架的灵魂------反射

反射之所以被称为框架的灵魂,是因为它赋予了我们在运行时分析类以及执行类中方法的能力。

通过反射你可以获取任意一个类的所有属性和方法,你还可以调用这些方法和属性

一.反射的应用场景?

像 Spring/Spring Boot、MyBatis 等等框架中都大量使用了反射机制。

这些框架中也大量使用了动态代理,而动态代理的实现也依赖反射。

1.加载数据库驱动

//1.DriverManager
DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());
//2.Class.forName
Class.forName("com.mysql.cj.jdbc.Driver");

2.xml或properties等配置文件加载

Spring通过XML配置模式装载Bean的过程

  • 将程序中所有XML或properties配置文件加载入内存
  • Java类里面解析xml或者properties里面的内容,得到对应实体类的字节码字符串以及相关的属性信息
  • 使用反射机制,根据这个字符串获得某个类的Class实例
  • 动态配置实例的属性

配置文件

className=com.example.reflectdemo.TestInvokemethodName=printlnState

实体类

public class TestInvoke {    
    private void printlnState(){        
        System.out.println("I am fine");    
    }
}

?解析配置文件内容

// 解析xml或properties里面的内容,得到对应实体类的字节码字符串以及属性信息
public static String getName(String key) throws IOException {
    Properties properties = new Properties();
    FileInputStream in = new FileInputStream("D:\IdeaProjects\AllDemos\language-specification\src\main\resources\application.properties");
    properties.load(in);
    in.close();
    return properties.getProperty(key);
}

利用反射获取实体类的Class实例,创建实体类的实例对象,调用方法

public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException, ClassNotFoundException, InstantiationException {
    // 使用反射机制,根据这个字符串获得Class对象
    Class<?> c = Class.forName(getName("className"));                                        
    System.out.println(c.getSimpleName());
    // 获取方法
    Method method = c.getDeclaredMethod(getName("methodName"));
    // 绕过安全检查
    method.setAccessible(true);
    // 创建实例对象
    TestInvoke testInvoke = (TestInvoke)c.newInstance();
    // 调用方法
    method.invoke(testInvoke);}

二.反射机制的优缺点

优点?: 可以让咱们的代码更加灵活、为各种框架提供开箱即用的功能提供了便利

缺点?:让我们在运行时有了分析操作类的能力,这同样也增加了安全问题。比如可以无视泛型参数的安全检查(泛型参数的安全检查发生在编译时)。另外,反射的性能也要稍差点,不过,对于框架来说实际是影响不大的

三.获取 Class 对象的四种方式

Java 提供了四种方式获取 Class 对象:

1. 知道具体类的情况下可以使用:

Class targetClass = TargetObject.class;

但是我们一般是不知道具体类的,基本都是通过遍历包下面的类来获取 Class 对象,通过此方式获取 Class 对象不会进行初始化

2. 通过?Class.forName()传入类的全路径获取:

Class targetClass = Class.forName("com.lzm.TargetObject");

3. 通过对象实例instance.getClass()获取:

TargetObject o = new TargetObject();
Class targetClass = o.getClass();

4. 通过类加载器xxxClassLoader.loadClass()传入类路径获取:

Class clazz = ClassLoader.loadClass("com.lzm.TargetObject");

通过类加载器获取 Class 对象不会进行初始化,意味着不进行包括初始化等一系列步骤,静态代码块和静态对象不会得到执行

四.反射的一些基本操作

1.创建一个我们要使用反射操作的类?TargetObject

?

package com.lzm;

public class TargetObject {
    private String value;

    public TargetObject(){
        value="lzm";
    }
    public void publicMethod(String s){
        System.out.println("I am "+s);
    }
    private void privateMethod(){
        System.out.println("value is "+value);
    }
}
2.使用反射操作这个类的方法以及参数
???????
package com.lzm;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Reflection {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        /**
         * 获取TargetObject类的Class对象并且创建TargetObject类实例
         */
        Class<?> targetClass=Class.forName("com.lzm.TargetObject");
        TargetObject targetObject= (TargetObject) targetClass.newInstance();
        /**
         * 获取TargetObject类中定义的所有方法
         */
        Method[] methods=targetClass.getDeclaredMethods();
        for(Method method:methods){
            System.out.println(method.getName());
        }
        /**
         * 获取指定方法并调用
         */
        Method publicMethod=targetClass.getDeclaredMethod("publicMethod", String.class);
        publicMethod.invoke(targetObject,"lzmzcc");
        /**
         * 获取指定参数并对参数进行修改
         */
        Field field = targetClass.getDeclaredField("value");
        //为了对类中的参数进行修改,所以取消安全检查
        field.setAccessible(true);
        field.set(targetObject,"lzmzcc");
        /**
         * 调用private方法
         */
        Method privateMethod = targetClass.getDeclaredMethod("privateMethod");
        privateMethod.setAccessible(true);
        privateMethod.invoke(targetObject);

    }
}

输出内容:

?

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-04-18 17:27:33  更:2022-04-18 17:29:31 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 5:07:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码