1.反射
正射:Person person = new Person();
反射:我们只知道这个类的一些基本信息,就好像我们看电影的时候,为了抓住一个犯罪嫌疑人,警察就会问一些目击证人,根据这些证人提供的信息,找专家把犯罪嫌疑人的样貌给画出来——这个过程,就可以称之为反射。
反射的缺点:
- 破坏封装:由于反射允许访问私有字段和私有方法,所以可能会破坏封装而导致安全问题。
- 性能开销:由于反射涉及到动态解析,因此无法执行 Java 虚拟机优化,再加上反射的写法的确要复杂得多,所以性能要比“正射”差很多,在一些性能敏感的程序中应该避免使用反射。
反射的主要应用场景:
- 开发通用框架:像 Spring,为了保持通用性,通过配置文件来加载不同的对象,调用不同的方法。
- 动态代理:在面向切面编程中,需要拦截特定的方法,就会选择动态代理的方式,而动态代理的底层技术就是反射。
- 注解:注解本身只是起到一个标记符的作用,它需要利用发射机制,根据标记符去执行特定的行为。
eg
public class ReflectionDemo1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Writer writer = new Writer();
writer.setName("沉默王二");
System.out.println(writer.getName());
Class clazz = Class.forName("com.itwanger.s39.Writer");
Constructor constructor = clazz.getConstructor();
Object object = constructor.newInstance();
Method setNameMethod = clazz.getMethod("setName", String.class);
setNameMethod.invoke(object, "沉默王二");
Method getNameMethod = clazz.getMethod("getName");
System.out.println(getNameMethod.invoke(object));
}
}
2.反射中的Class对象
在 Java 中,Class 对象是一种特殊的对象,它代表了程序中的类和接口。
Java 中的每个类型(包括类、接口、数组以及基础类型)在 JVM 中都有一个唯一的 Class 对象与之对应。这个 Class 对象被创建的时机是在 JVM 加载类时,由 JVM 自动完成。
Class 对象中包含了与类相关的很多信息,如类的名称、类的父类、类实现的接口、类的构造方法、类的方法、类的字段等等。这些信息通常被称为元数据(metadata)。
除了前面提到的,通过类的全名获取 Class 对象,还有以下两种方式:
- 如果你有一个类的实例,你可以通过调用该实例的
getClass()
方法获取 Class 对象。例如:String str = "Hello World"; Class cls = str.getClass();
- 如果你有一个类的字面量(即类本身),你可以直接获取 Class 对象。例如:
Class cls = String.class;
要想使用反射,首先需要获得反射类的 Class 对象,每一个类,不管它最终生成了多少个对象,这些对象只会对应一个 Class 对象,这个 Class 对象是由 Java 虚拟机生成的,由它来获悉整个类的结构信息。
也就是说,java.lang.Class
是所有反射 API 的入口。
3.JVM
说白了,就是让Java代码在JVM虚拟机上运行,这样就实现了跨平台均可运行。
JVM 大致可以划分为三个部分,分别是类加载器(Class Loader)、运行时数据区(Runtime Data Areas)和执行引擎(Excution Engine)。
类加载器:类加载器用来加载.class文件,类加载器负责将字节码文件加载到内存中,主要会经历加载->连接->实例化这三个阶段。
运行时数据区:JVM 定义了 Java 程序运行期间需要使用到的内存区域,简单来说,这块内存区域存放了字节码信息以及程序执行过程的数据,垃圾回收器也会针对运行时数据区进行对象回收的工作。
执行引擎:主要用来干具体的事。“虚拟机”是一个相对于“物理机”的概念,这两种机器都有代码执行能力,其区别是物理机的执行引擎是直接建立在处理器、缓存、指令集和操作系统层面上的,而虚拟机的执行引擎则是由软件自行实现的,因此可以不受物理条件制约地定制指令集与执行引擎的结构关系,能够执行那些不被硬件直接支持的指令集格式。简单来说,JVM 中的执行引擎充当了将高级语言翻译为机器语言的译者。
总的来说,JVM 是 Java 程序执行的环境,它隐藏了底层操作系统和硬件的复杂性,提供了一个统一、稳定和安全的运行平台。
idea的编译按钮会帮我们生成.class文件。
4.字节码文件
5.AOP
AOP,也就是 Aspect-oriented Programming,译为面向切面编程,是计算机科学中的一个设计思想,旨在通过切面技术为业务主体增加额外的通知(Advice),从而对声明为“切点”(Pointcut)的代码块进行统一管理和装饰。
AOP 是对面向对象编程(Object-oriented Programming,俗称 OOP)的一种补充,OOP 的核心单元是类(class),而 AOP 的核心单元是切面(Aspect)。
我们可以简单的把 AOP 理解为贯穿于方法之中,在方法执行前、执行时、执行后、返回值后、异常后要执行的操作。
eg:
6.IOC
控制反转就是把创建和管理 bean 的过程转移给了第三方。而这个第三方,就是 Spring IoC Container,对于 IoC 来说,最重要的就是容器。
容器负责创建、配置和管理 bean,也就是它管理着 bean 的生命,控制着 bean 的依赖(属性或者引用)注入。通俗点讲,因为项目中每次创建对象是很麻烦的,所以我们使用 Spring IoC 容器来管理这些对象,需要的时候你就直接用,不用管它是怎么来的、什么时候要销毁,只管用就好了。
7.IOC容器
BeanFactory:可以看成一个HashMap
- Key - bean name
- Value - bean object
但它一般只有 get, put 两个功能,所以称之为“低级容器”。
ApplicationContext:升级版IOC容器,多了许多功能。ApplicationContext有两个具体的实现子类,用来读取配置文件:
ClassPathXmlApplicationContext:通过ClassPath读取配置文件,常用。
FileSystemXmlApplicationContext
:本地读取配置文件,不常用。
使用Spring IOC容器,一定要生成Bean的set()方法,因为IOC容器就是使用这个set()方法完成注入的。
8.依赖注入
依赖:程序运行需要依赖外部的资源,提供程序内对象的所需要的数据、资源。
配置文件把资源从外部注入到内部,容器加载了外部的文件、对象、数据,然后把这些资源注入给程序内的对象,维护了程序内外对象之间的依赖关系。