1. 有哪些注解可以注入 Bean?@Autowired 和 @Resource 的区别?
在 Spring 框架中,常用的注入 Bean 的注解包括:
@Autowired
:自动注入,按照类型自动装配,如果有多个同类型的 Bean,则需要通过 @Qualifier 指定具体的 Bean。
@Resource
:Java 自带的注入方式,按照名称自动装配,默认是按照属性名称进行匹配,如果需要按照 Bean 的名称进行匹配,可以使用 @Resource(name="beanName")。
@Inject
:和 @Autowired 类似,也是按照类型进行自动装配,但是 @Inject 注解是 JSR-330 提供的,而 @Autowired 注解是 Spring 框架提供的。
@Value
:用于注入配置文件中的属性值,可以指定默认值。
@Component
:用于声明一个 Bean,作用类似于 XML 中的 <bean> 标签。以上注解都可以用于注入 Bean,不同的注解之间的区别主要在于注入方式和实现方式的不同。@Autowired 和 @Resource 最常用
@Autowired 按照类型自动装配更为常用.
@Resource 按照名称自动装配则比较适合需要明确指定 Bean 名称的情况。
需要注意的是,注入 Bean 的时候最好使用接口类型作为注入对象,这样可以避免因为具体实现类变更导致注入失败的问题。
2. 请你介绍下 JVM 内存模型,分为哪些区域?各区域的作用是什么?
JVM 内存模型分为以下几个区域:
程序计数器(Program Counter Register):每个线程都有自己的程序计数器,用于指示当前线程执行的字节码指令的行号,以便线程执行时能够回到正确的位置。
虚拟机栈(JVM Stack):也称为 Java 方法栈,用于存储方法执行时的局部变量表、操作数栈、动态链接、方法出口等信息。每个线程在执行一个方法时,都会为该方法分配一个栈帧,并将该栈帧压入虚拟机栈,当方法执行完毕后,虚拟机会将其出栈。
本地方法栈(Native Method Stack):与虚拟机栈类似,用于存储本地方法的执行信息。
堆(Heap):用于存储对象实例,是 JVM 中最大的一块内存区域。堆是被所有线程共享的,当创建一个新对象时,对象实例存储在堆中,堆中存储的对象实例都有一个标记用于标记对象是否存活。垃圾回收器会周期性地回收那些没有被标记为存活的对象。
方法区(元空间)(Method Area):用于存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。方法区也是被所有线程共享的,在JDK1.8之前的版本里,代表JVM的一块区域。在1.8版本以后,这块区域的名字改了,叫做“Matespace”。
运行时常量池(Runtime Constant Pool):是方法区的一部分,用于存储编译期间生成的各种字面量和符号引用,这些内容在类加载后进入常量池中。
其中,程序计数器、虚拟机栈、本地方法栈是线程私有的,堆、方法区、运行时常量池是线程共享的。
3. Linux 中的硬链接和软连接是什么,二者有什么区别?
在 Linux 文件系统中,硬链接(hard link)和软链接(symbolic link)都是一种文件链接的方式,可以用于将一个文件链接到另一个文件上。它们的主要区别在于创建方式、所占空间和使用限制等方面。
硬链接是通过在文件系统中创建一个新的目录项(directory entry)指向同一文件 inode 的位置来实现的。因为硬链接实际上是指向同一 inode,所以如果原文件被删除,硬链接依然能够访问到原文件的内容。硬链接的使用范围比较受限,因为硬链接只能指向同一个文件系统内的文件,不能跨文件系统创建。
软链接是通过在文件系统中创建一个新的文件来实现的,该文件中包含指向另一个文件的路径。软链接可以跨文件系统创建,并且可以指向任何类型的文件。但是,当原文件被删除时,软链接将会失效。
总的来说,硬链接更加高效,因为它只是添加了一个新的目录项,所以对磁盘空间的消耗比软链接要小。但是,硬链接不能跨文件系统,所以在实际应用中需要根据具体的需求来选择使用哪种链接方式。