JAVA反射机制以及常见应用场景

前言:

反射机制是JAVA的核心知识点之一,大多数框架的实现原理就是利用了反射机制,掌握反射机制会使你学习框架更加轻松高效

一、JAVA中的反射指的是什么?

回答上面这个问题的时候,我们先讨论下class的加载方式和流程

1、一个java文件通过javac编译后得到class文件

2、当我们执行了初始化操作的时候(可能时new,也有可能时父类初始化,子类初始化,反射...),会将class文件通过类加载器加载到jvm中,

3、将.class文件加载到JVM中,会分成好几个步骤,中间有加载,链接,初始化

4、在加载的过程中,会在java堆中创建一个java.lang.Class的对象,这个对象就代表这类相关的信息

5、java中的反射就是利用了Class这个类去实现的

如下图:

JAVA反射机制以及常见应用场景_第1张图片

 

这时候就引发了一个问题?常见的new对象的方式和这种有什么区别呢?

new对象的方式:编译期已经确定类型,且性能会比反射好,但是灵活性不强,尤其在现代工业中(PS:需求一天一变)

反射:使用时动态调用创建,性能略差但是灵活,在现在框架中大量使用

二、java.lang.Class这个类

1、用于获取与类相关的各种信息, 提供了获取类信息的相关方法
2、Class类继承自Object类

3、Class类是所有类的共同的图纸

4、每个类有自己的对象,同时每个类也看做是一个对象,有共同的图纸Class,存放类的结构信息,能够通过相应方法取出相应的信息:类的名字、属性、方法、构造方法、父类和接口。

5、没有构造方法,通过jvm加载而出

三、获取反射入口(class对象)的三种方法

要想操作反射,必须先拿到反射的入口

1,通过通过Class.forName("全类名")

try {
            Class perClazz = Class.forName("reflect_fanshe.Person");
            System.out.println(perClazz);
        } catch (ClassNotFoundException e) {
            
            e.printStackTrace();
        }

2、类名.class

Class perClazz2 = Person.class;

3、对象.getClass()

Person person = new Person();
Class perClazz3 = person.getClass();

四、可以使用拿到的反射入口class获取类的各种信息

1:perClazz.getMethods()  获取此类的所有public方法(父类的,实现接口的,自己的)

Class perClazz = null;
        try {
            perClazz = Class.forName("reflect_fanshe.Person");
        } catch (ClassNotFoundException e) {
            
            e.printStackTrace();
        }
        Method[] methods = perClazz.getMethods();
                //遍历所有方法
        for (Method method : methods) {
            System.out.println(method);
        }
    }

2:获取所有的构造方法

3、 获取父类

 

4、获取当前类(只有本类的)的所有方法和属性,包括私有的

暴力反射?

获取类的私有成员。通过setAccessible(true)方法,设置成可访问。

 

field.setAccessible(true); // 私有变量必须设置访问权限为true

五、反射的使用场景

1、可以用于改进设计模式 

例:对工厂模式的改进

常规工厂模式

interface Fruit {
 
void eat();
 
}

class Apple implements Fruit {
    public void eat(){
        System.out.println("Eat Apple");
    }
}

class Orange implements Fruit {
    public void eat(){
        System.out.println("Eat Orange");
    }
}

//编译时就确定类型,不够灵活,不好新增,如果我要新增一个实现类,就要在工厂类中改代码,耦合度较高。

public class Factory {
 
public static Fruit getInstance(String fruitName){
 
Fruit f=null;
 
        if("Apple".equals(fruitName)){
 
        f=new Apple();
 
        }
 
if("Orange".equals(fruitName)){
 
f=new Orange();
 
        }
 
return f;
 
    }
 
}

改进后

public class ReflexFactory {
 
public static Fruit2 getInstances(String className) {
 
Fruit2 f2 =null;
 
        try {
 
            //利用反射
 
            f2 = (Fruit2)Class.forName(className).newInstance();
 
        }catch (Exception e) {
 
e.printStackTrace();
 
        }
 
return f2;
 
    }
 
}

当如果要新增实现类的话,只要将传入的参数改变就好,无需更改工厂内的代码。

 

2、 反射机制的典型应用---Tomcat服务器

1).Tomcat服务器应用到的Java的三大技术

IO技术ServerSocket技术反射技术

2).Tomcat服务器大致处理用户应答的思路

(1).对外暴露接口---->著名的Servlet (服务器脚本片段)

[1]. 对外提供接口的原因具体处理客户端应答请求的方式不一样的。应该根据具体的请求来进行具体的处理。向上抽取形成Servlet接口并提供给客户端使用。

[2]. 由开发者来实现Servlet接口定义的具体应答请求的处理方式

(2).提供配置文件---->web.xml (WEB宏观部署描述文件)

每个Web应用程序都有自己的配置文件web.xml告知Tomcat服务器(App)有哪些用户自定义的Servlet实现类

3).Tomcat具体加载处理细节

(1). Tomcat(App)首先读取配置文件web.xml中配置好的Servlet的子类名称

(2).Tomcat根据读取到的客户端实现的Servlet子类的类名字符串去寻找对应的字节码文件。如果找到就将其加载到内存。

(3).Tomcat通过预先设置好的Java反射处理机制解析字节码文件并创建相应的实例对象。之后调用所需要的方法。

【最后】Tomcat一启动,用户自定义的Servlet的子类通过Tomcat内部的反射框架也随之运行。

3、在项目中处处可见,AOP和IOC都是基于反射实现的

例:拦截器,注解、XML文档、token登录拦截

参考博客

https://blog.csdn.net/weixin_42724467/article/details/84311385

https://blog.csdn.net/21aspnet/article/details/89402714

https://blog.csdn.net/u010349644/article/details/82498452

https://blog.csdn.net/qq_23143621/article/details/100537532

https://blog.csdn.net/jinwufeiyang/article/details/80115119

https://blog.csdn.net/qq_37469998/article/details/88729423

 

 

你可能感兴趣的:(JAVA)