总结:心得体会
既然选择这个行业,选择了做一个程序员,也就明白只有不断学习,积累实战经验才有资格往上走,拿高薪,为自己,为父母,为以后的家能有一定的经济保障。
学习时间都是自己挤出来的,短时间或许很难看到效果,一旦坚持下来了,必然会有所改变。不如好好想想自己为什么想进入这个行业,给自己内心一个答案。
面试大厂,最重要的就是夯实的基础,不然面试官随便一问你就凉了;其次会问一些技术原理,还会看你对知识掌握的广度,最重要的还是你的思路,这是面试官比较看重的。
最后,上面这些大厂面试真题都是非常好的学习资料,通过这些面试真题能够看看自己对技术知识掌握的大概情况,从而能够给自己定一个学习方向。包括上面分享到的学习指南,你都可以从学习指南里理顺学习路线,避免低效学习。
大厂Java架构核心笔记(适合中高级程序员阅读):
-
2、多个AOP的顺序怎么定
-
3、Spring 的 AOP 有哪几种创建代理的方式
-
4、JDK 动态代理和 Cglib 代理的区别
-
5、JDK 动态代理为什么只能对实现了接口的类生成代理
-
6、BeanFactory 和 FactoryBean 的区别
-
7、BeanFactory 和 ApplicationContext 的区别
-
8、Spring IoC 的容器构建流程
-
9、Spring bean 的生命周期
-
10、Spring 的事务传播行为有哪些
-
11、Spring 的事务隔离级别
-
12、Spring 的事务隔离级别是如何做到和数据库不一致的?
-
13、Spring 事务的实现原理
-
14、Spring 怎么解决循环依赖的问题
-
15、Spring 能解决构造函数循环依赖吗
-
16、Spring 三级缓存
-
17、@Resource 和 @Autowire 的区别
-
18、@Autowire 怎么使用名称来注入
-
19、@PostConstruct 修饰的方法里用到了其他 bean 实例,会有问题吗
-
20、bean 的 init-method 属性指定的方法里用到了其他 bean 实例,会有问题吗
-
21、要在 Spring IoC 容器构建完毕之后执行一些逻辑,怎么实现
-
22、Spring 中的常见扩展点有哪些
-
23、Spring中如何让两个bean按顺序加载?
-
24、使用 Mybatis 时,调用 DAO接口时是怎么调用到 SQL 的
1、Spring 的 AOP 是怎么实现的
本质是通过动态代理来实现的,主要有以下几个步骤。
- 获取增强器,例如被
Aspect
注解修饰的类。
- 在创建每一个
bean
时,会检查是否有增强器能应用于这个bean
,简单理解就是该bean
是否在该增强器指定的execution
表达式中。如果是,则将增强器作为拦截器参数,使用动态代理创建 bean 的代理对象实例。
- 当我们调用被增强过的
bean
时,就会走到代理类中,从而可以触发增强器,本质跟拦截器
类似。
2、多个AOP的顺序怎么定
通过 Ordered 和 PriorityOrdered 接口进行排序。PriorityOrdered 接口的优先级比 Ordered 更高,如果同时实现 PriorityOrdered 或 Ordered 接口,则再按 order 值排序,值越小的优先级越高。
3、Spring 的 AOP 有哪几种创建代理的方式
Spring 中的 AOP 目前支持 JDK 动态代理和 Cglib 代理。
通常来说:如果被代理对象实现了接口,则使用 JDK 动态代理,否则使用 Cglib 代理。另外,也可以通过指定 proxyTargetClass=true 来实现强制走 Cglib 代理。
4、JDK 动态代理和 Cglib 代理的区别
- JDK 动态代理本质上是实现了被代理对象的接口,而 Cglib 本质上是继承了被代理对象,覆盖其中的方法。
- JDK 动态代理只能对实现了接口的类生成代理,Cglib 则没有这个限制。但是 Cglib 因为使用继承实现,所以 Cglib 无法代理被 final 修饰的方法或类。
- 在调用代理方法上,JDK 是通过反射机制调用,Cglib是通过FastClass 机制直接调用。FastClass 简单的理解,就是使用 index 作为入参,可以直接定位到要调用的方法直接进行调用。
- 在性能上,JDK1.7 之前,由于使用了 FastClass 机制,Cglib 在执行效率上比 JDK 快,但是随着 JDK 动态代理的不断优化,从 JDK 1.7 开始,JDK 动态代理已经明显比 Cglib 更快了。
5、JDK 动态代理为什么只能对实现了接口的类生成代理
根本原因是通过 JDK 动态代理生成的类已经继承了 Proxy 类,所以无法再使用继承的方式去对类实现代理。
6、BeanFactory 和 FactoryBean 的区别
BeanFactory
:Spring 容器最核心也是最基础的接口,本质是个工厂类,用于管理 bean 的工厂,最核心的功能是加载 bean,也就是 getBean 方法,通常我们不会直接使用该接口,而是使用其子接口。
FactoryBean
:该接口以 bean 样式定义,但是它不是一种普通的 bean,它是个工厂 bean,实现该接口的类可以自己定义要创建的 bean 实例,只需要实现它的 getObject 方法即可。
FactoryBean
被广泛应用于 Java 相关的中间件中,如果你看过一些中间件的源码,一定会看到 FactoryBean 的身影。
一般来说,都是通过
FactoryBean
的getObject 来返回一个代理类,当我们触发调用时,会走到代理类中,从而可以在代理类中实现中间件的自定义逻辑,比如:RPC 最核心的几个功能,选址、建立连接、远程调用,还有一些自定义的监控、限流等等。
7、BeanFactory 和 ApplicationContext 的区别
BeanFactory:基础 IoC 容器,提供完整的 IoC 服务支持。
ApplicationContext:高级 IoC 容器,BeanFactory 的子接口,在 BeanFactory 的基础上进行扩展。包含 BeanFactory 的所有功能,还提供了其他高级的特性,比如:事件发布、国际化信息支持、统一资源加载策略等。正常情况下,我们都是使用的 ApplicationContext。
这边以电话来举个简单的例子:
我们家里使用的 “座机” 就类似于 BeanFactory,可以进行电话通讯,满足了最基本的需求。
而现在非常普及的智能手机,iPhone、小米等,就类似于 ApplicationContext,除了能进行电话通讯,还有其他很多功能:拍照、地图导航、听歌等。
8、Spring IoC 的容器构建流程
核心的构建流程如下,也就是 refresh
方法的核心内容:
9、Spring bean 的生命周期
bean 的生命周期主要有以下几个阶段,深色底的5个是比较重要的阶段:
10、Spring 的事务传播行为有哪些
1)REQUIRED:Spring 默认的事务传播级别,如果上下文中已经存在事务,那么就加入到事务中执行,如果当前上下文中不存在事务,则新建事务执行。
2)REQUIRES_NEW:每次都会新建一个事务,如果上下文中有事务,则将上下文的事务挂起,当新建事务执行完成以后,上下文事务再恢复执行。
3)SUPPORTS:如果上下文存在事务,则加入到事务执行,如果没有事务,则使用非事务的方式执行。
4)MANDATORY:上下文中必须要存在事务,否则就会抛出异常。
5)NOT_SUPPORTED :如果上下文中存在事务,则挂起事务,执行当前逻辑,结束后恢复上下文的事务。
6)NEVER:上下文中不能存在事务,否则就会抛出异常。
7)NESTED:嵌套事务。如果上下文中存在事务,则嵌套事务执行,如果不存在事务,则新建事务。
11、Spring 的事务隔离级别
Spring 的事务隔离级别底层其实是基于数据库的,Spring 并没有自己的一套隔离级别。
DEFAULT:使用数据库的默认隔离级别。
READ_UNCOMMITTED:读未提交,最低的隔离级别,会读取到其他事务还未提交的内容,存在脏读。
READ_COMMITTED:读已提交,读取到的内容都是已经提交的,可以解决脏读,但是存在不可重复读。
REPEATABLE_READ:可重复读,在一个事务中多次读取时看到相同的内容,可以解决不可重复读,但是存在幻读。
SERIALIZABLE:串行化,最高的隔离级别,对于同一行记录,写会加写锁,读会加读锁。在这种情况下,只有读读能并发执行,其他并行的读写、写读、写写操作都是冲突的,需要串行执行。可以防止脏读、不可重复度、幻读,没有并发事务问题。
12、Spring 的事务隔离级别是如何做到和数据库不一致的?
比如数据库是可重复读,Spring 是读已提交,这是怎么实现的?
Spring 的事务隔离级别本质上还是通过数据库来控制的,具体是在执行事务前先执行命令修改数据库隔离级别,命令格式如下:
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED
13、Spring 事务的实现原理
Spring 事务的底层实现主要使用的技术:AOP(动态代理) + ThreadLocal + try/catch。
动态代理:基本所有要进行逻辑增强的地方都会用到动态代理,AOP 底层也是通过动态代理实现。
ThreadLocal:主要用于线程间的资源隔离,以此实现不同线程可以使用不同的数据源、隔离级别等等。
try/catch:最终是执行 commit 还是 rollback,是根据业务逻辑处理是否抛出异常来决定。
Spring 事务的核心逻辑伪代码如下:
public void invokeWithinTransaction() {
// 1.事务资源准备
try {
// 2.业务逻辑处理,也就是调用被代理的方法
} catch (Exception e) {
// 3.出现异常,进行回滚并将异常抛出
} finally {
// 现场还原:还原旧的事务信息
}
// 4.正常执行,进行事务的提交
// 返回业务逻辑处理结果
}
详细流程如下图所示:
14、Spring 怎么解决循环依赖的问题
Spring 是通过提前暴露 bean 的引用来解决的,具体如下。
Spring 首先使用构造函数创建一个 “不完整” 的 bean 实例(之所以说不完整,是因为此时该 bean 实例还未初始化),并且提前曝光该 bean 实例的 ObjectFactory(提前曝光就是将 ObjectFactory 放到 singletonFactories 缓存).
通过 ObjectFactory 我们可以拿到该 bean 实例的引用,如果出现循环引用,我们可以通过缓存中的 ObjectFactory 来拿到 bean 实例,从而避免出现循环引用导致的死循环。
举个例子:A 依赖了 B,B 也依赖了 A,那么依赖注入过程如下:
- 检查 A 是否在缓存中,发现不存在,进行实例化
- 通过构造函数创建 bean A,并通过 ObjectFactory 提前曝光 bean A
- A 走到属性填充阶段,发现依赖了 B,所以开始实例化 B。
- 首先检查 B 是否在缓存中,发现不存在,进行实例化
- 通过构造函数创建 bean B,并通过 ObjectFactory 曝光创建的 bean B
- B 走到属性填充阶段,发现依赖了 A,所以开始实例化 A。
- 检查 A 是否在缓存中,发现存在,拿到 A 对应的 ObjectFactory 来获得 bean A,并返回。
- B 继续接下来的流程,直至创建完毕,然后返回 A 的创建流程,A 同样继续接下来的流程,直至创建完毕。
- 这边通过缓存中的 ObjectFactory 拿到的 bean 实例虽然拿到的是 “不完整” 的 bean 实例,但是由于是单例,所以后续初始化完成后,该 bean 实例的引用地址并不会变,所以最终我们看到的还是完整 bean 实例。
15、Spring 能解决构造函数循环依赖吗
答案是不行的,对于使用构造函数注入产生的循环依赖,Spring 会直接抛异常。
为什么无法解决构造函数循环依赖?
上面解决逻辑的第一句话:“首先使用构造函数创建一个 “不完整” 的 bean 实例”,从这句话可以看出,构造函数循环依赖是无法解决的,因为当构造函数出现循环依赖,我们连 “不完整” 的 bean 实例都构建不出来。
16、Spring 三级缓存
Spring 的三级缓存其实就是解决循环依赖时所用到的三个缓存。
singletonObjects:正常情况下的 bean 被创建完毕后会被放到该缓存,key:beanName,value:bean 实例。
singletonFactories:上面说的提前曝光的 ObjectFactory 就会被放到该缓存中,key:beanName,value:ObjectFactory。
earlySingletonObjects:该缓存用于存放 ObjectFactory 返回的 bean,也就是说对于一个 bean,ObjectFactory 只会被用一次,之后就通过 earlySingletonObjects 来获取,key:beanName,早期 bean 实例。
17、@Resource 和 @Autowire 的区别
1、@Resource 和 @Autowired 都可以用来装配 bean
2、@Autowired 默认按类型装配,默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false。
3、@Resource 如果指定了 name 或 type,则按指定的进行装配;如果都不指定,则优先按名称装配,当找不到与名称匹配的 bean 时才按照类型进行装配。
18、@Autowire 怎么使用名称来注入
最后
文章中涉及到的知识点我都已经整理成了资料,录制了视频供大家下载学习,诚意满满,希望可以帮助在这个行业发展的朋友,在论坛博客等地方少花些时间找资料,把有限的时间,真正花在学习上,所以我把这些资料,分享出来。相信对于已经工作和遇到技术瓶颈的朋友们,在这份资料中一定都有你需要的内容。
进行装配;如果都不指定,则优先按名称装配,当找不到与名称匹配的 bean 时才按照类型进行装配。
18、@Autowire 怎么使用名称来注入
最后
文章中涉及到的知识点我都已经整理成了资料,录制了视频供大家下载学习,诚意满满,希望可以帮助在这个行业发展的朋友,在论坛博客等地方少花些时间找资料,把有限的时间,真正花在学习上,所以我把这些资料,分享出来。相信对于已经工作和遇到技术瓶颈的朋友们,在这份资料中一定都有你需要的内容。