"/>
侧边栏壁纸
博主头像
PySuper 博主等级

千里之行,始于足下

  • 累计撰写 286 篇文章
  • 累计创建 17 个标签
  • 累计收到 2 条评论

目 录CONTENT

文章目录

Java Spring 概念

PySuper
2023-01-06 / 0 评论 / 0 点赞 / 5 阅读 / 0 字
温馨提示:
所有牛逼的人都有一段苦逼的岁月。 但是你只要像SB一样去坚持,终将牛逼!!! ✊✊✊

一、概念

Spring 的核心思想说说你的理解

IOC、DI、AOP

IOC和AOP是通过什么机制来实现的?

  • IOC: 反射、依赖注入、设计模式-工厂模式、容器实现。

  • AOP:JDK 动态代理,AOP 代理

依赖倒置,依赖注入,控制反转分别是什么?

依赖注入了解吗?怎么实现依赖注入的?

如果让你设计一个Spring Ioc,你觉得会从哪些方面考虑这个设计?

Bean的单例和非单例,生命周期是否一样?

Spring bean的作用域有哪些?

在Spring中,在bean加载/销毁前后,如果想实现某些逻辑,可以怎么做?

二、理解

定义

  • Spring 是一个生态,可以构建 Java 应用所需的一切基础措施

  • 通常 Spring 指的就是 Spring Framework

核心解释

  • Spring 是一个轻量级的开源容器框架

  • Spring 是为了解决企业级应用开发的业务逻辑和其他各层对象和对象直接的耦合问题

  • Spring 是一个 IOC 和 AOP 的容器框架

概念

  • IOC: 控制反转

  • AOP:面向切面编程

  • 容器:包含并管理应用对象的生命周期

补充:可以把 Spring 官网的图贴下

优缺点

优点

  • 方便解耦,简化开发

    • 通过 Spring 提供的 IoC 容器,可以将对象间的依赖关系交由 Spring 进行控制,避免硬编码所造成的过度程序耦合

    • 用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。

  • AOP编程的支持

    • 通过 Spring 的 AOP 功能,方便进行面向切面的编程

    • 许多不容易用传统 OOP 实现的功能可以通过 AOP 轻松实现

  • 声明式事务的支持

    • 可以将我们从单调烦闷的事务管理代码中解脱出来

    • 通过声明式方式灵活的进行事务的管理,提高开发效率和质量

  • 方便程序的测试

    • 可以用非容器依赖的编程方式进行几乎所有的测试工作

    • 测试不再是昂贵的操作,而是随手可做的事情

  • 方便集成各种优秀框架

    • Spring 可以降低各种框架的使用难度,提供了对各种优秀框架(Struts、Hibernate、Hessian、Quartz等)的直接支持

  • 降低 JavaEE API 的使用难度

    • Spring 对 JavaEE API(如 JDBC、JavaMail、远程调用等)进行了薄薄的封装层,使这些 API 的使用难度大为降低

  • Java 源码是经典学习范例

    • Spring 的源代码设计精妙、结构清晰、匠心独用,处处体现着大师对 Java 设计模式灵活运用以及对 Java 技术的高深造诣

    • 它的源代码无意是 Java 技术的最佳实践的范例

缺点

  1. 学习曲线较陡:由于 Spring 框架提供了丰富的功能和模块,对于初学者来说,学习和掌握Spring框架需要花费一定的时间和精力

  2. 配置复杂:在使用 Spring 框架时,需要进行大量的XML或注解配置,这在一定程度上增加了开发者的工作量和代码的维护成本

  3. 运行效率:由于 Spring 框架提供了大量的功能和灵活性,会增加一定的运行时开销,导致应用的运行效率相对较低

  4. 引入了第三方依赖:在使用 Spring 框架时,需要引入一些第三方库来支持其功能,这增加了应用的复杂性和部署的难度

松紧耦合

紧耦合和松耦合有什么区别?如何编写松耦合的代码?

  • 紧耦合:紧密耦合是指类之间高度依赖(通过 new 创建对象)

  • 松耦合:松耦合是通过促进单一职责和接口分离、依赖倒置的设计原则来实现

IOC

IOC 是什么?作用、优点是什么?

参考 什么是 Spring IOC?有什么作用?open in new window

定义

作用

优缺点

实现机制

简单工厂和反射

详见 IOC 的实现原理—反射与工厂模式open in new window

IOC vs DI

IOC 和 DI 的区别是什么

IoC 是一种设计思想,而 DI 是一种具体的实现技术

可以参考 IoC 和 DI 有什么区别?open in new window理解

三、拓展

注解

@Component、@Controller、@Repository、@Service

@Component、@Controller、@Repository、@Service 有何区别?

  • @Component 是其他注解的原注解

  • 其他几个注解是为了让代码阅读性更好

@Autowired 和 @Resource 之间的区别

 @Autowired 和 @Resource 的区别主要体现在以下 5 点

  • 来源不同

  • 依赖查找的顺序不同

  • 支持的参数不同

  • 依赖注入的用法不同

  • 编译器 IDEA 的提示不同

可以参考 面试突击78:@Autowired 和 @Resource 有什么区别open in new window

单例 Bean

单例 Bean 是单例模式吗

通常来说,单例模式是指在一个 JVM 中,一个类只能构造出来一个对象,有很多方法来实现单例模式,比如懒汉模式,但是我们通常讲的单例模式有一个前提条件就是规定在一个 JVM 中。

那如果要在两个 JVM 中保证单例呢?那可能就要用分布式锁这些技术,这里的重点是,我们在讨论单例模式时,是要考虑范围的,而 Spring 中的单例 Bean 也是一种单例模式,只不过范围比较小,范围是 beanName,一个 beanName 对应同一个 Bean 对象,不同 beanName 可以对应不同的 Bean 对象(就算是同一个类也是可以的)

实例化 vs 初始化

Bean 的实例化和 Bean 的初始化有什么区别

Spring 在创建一个 Bean 对象时,会先创建出来一个 Java 对象,会通过反射来执行类的构造方法从而得到一个 Java 对象,而这个过程就是 Bean 的实例化
得到 Java 对象后,会进行依赖注入,依赖注入之后就会进行初始化了,而 Bean 的初始化就是调用前面创建出来的 Java 对象中特定的方法,比如 Java 对象实现了 InitializingBean 接口,那么初始化的时候就会执行 Java 对象的 afterPropertiesSet(),Spring 只会执行这个方法,并不关心方法做了什么,我们可以在这个方法中去对某个属性进行验证,或者直接给某个属性赋值都是可以的,反正 Bean 的初始化就是执行 afterPropertiesSet() 方法,或者执行自定义初始化的方法(如 init-method)。

线程安全

Spring 中 Bean 是线程安全的吗

Spring 本身并没有针对 Bean 做线程安全的处理,所以

  1. 如果 Bean 是无状态的,那么 Bean 则是线程安全的

  2. 如果 Bean 是有状态的,那么 Bean 则不是线程安全的

另外,Bean 是不是线程安全,跟 Bean 的作用域没有关系,Bean 的作用域只是表示 Bean 的生命周期范围,对于任何生命周期的 Bean 都是一个对象,这个对象是不是线程安全的,还是得看这个 Bean 对象本身

Spring 如何处理线程安全问题

  1. 如 UserService scope 配置为多例

  2. 将成员变量放置到 ThreadLocal 中

  3. 同步锁

BeanFactory vs ApplicationContext

BeanFactory 和 ApplicationContext 都是 Spring 容器中的两个核心接口,用于管理 Bean 对象的创建、配置、装配和管理

BeanFactory 接口是 Spring 的最基本的接口,提供了最简单的容器的实现。它通过配置文件中的 <bean> 标签来实例化和装配 Bean 对象,每次从容器中获取 Bean 时才真正创建对象

与 BeanFactory 不同,ApplicationContext 是对 BeanFactory 的拓展,提供了更加复杂的功能和定制化的配置,比如可以支持国际化、资源文件访问、事件发布等

与 BeanFactory 不同的是,它在容器创建时就已经将所有的 Bean 对象都实例化和装配好了,提供了更好的性能和可扩展性。进一步来说,BeanFactory 是 Spring 框架的基础设施,提供了最简单的容器服务,主要负责 Bean 的实例化、配置、管理等工作

ApplicationContext 是在 BeanFactory 基础上构建的,提供了更多可自动装配的 BeanFactory 接口实现,支持更多的功能,如国际化支持、事件传递、注解驱动等,同时也代表了 Spring 的一个完整整体

因此,ApplicationContext 相对于 BeanFactory 来说,功能更加全面强大,但是也比 BeanFactory 占用更多的系统资源。在实际应用中,如果仅仅需要实现 Bean 的实例化和简单的 Bean 的装配,可以使用 BeanFactory 接口;如果需要更多的功能,考虑使用 ApplicationContext 接口

BeanFactory vs FactoryBean

虽然 BeanFactory 和 FactoryBean 都与 Bean 的创建和管理有关,但它们在功能和使用上存在显著的区别

  • 功能不同:BeanFactory 负责管理和创建 Bean,而 FactoryBean 是一个接口,允许开发者实现定制化的 Bean 创建逻辑

  • 角色不同:BeanFactory 是 Spring 框架的核心,负责整个 Bean 的管理;而 FactoryBean 是 Bean 的创建方式之一,用于定制化的 Bean 实例化

  • 使用方式不同:BeanFactory 通常通过配置文件或者注解来实现 Bean 的管理和创建;而 FactoryBean 需要开发者实现自定义的工厂类,提供定制化的 Bean 创建逻辑

一些如细节如下

  • 如 FactoryBean 是懒加载对象(即用的时候才调用 FactoryBean.getBean() 方法)

  • BeanFactory.getBean("&xx") 可以获取 FactoryBean 对象,否则会获取 FactoryBean.getBean() 返回的对象

不完整的 Bean

Spring 如何在并发情况下获取不完整的 Bean

  • 主要原因是如下两个

    • getSingleton() 使用了双重检查锁

    • 对一级缓存加锁,加锁过程中,Bean 经过一个完整的生命周期,最后移除二、三级缓存,添加对象到一级缓存后才释放锁

注意:

为什么一级缓存不加到锁里面?

  • 性能:避免一级创建好的 Bean 阻塞等待

动态代理

JDK 动态代理和 CGLIB 动态代理有什么区别

Spring AOP 中的动态代理主要有两种方式、JDK 动态代理和 CGLIB 动态代理

  • JDK 动态代理只提供接口的代理,不支持类的代理

    • JDK 会在运行时为目标类生成一个动态代理类 $proxy*.class

    • 该代理类是实现了目标类接口,并且代理类会实现接口所有的方法增强代码

    • 调用时通过代理类先去调用处理类进行增强,再通过反射的方式进行调用目标方法。从而实现 AOP

  • 如果代理类没有实现接口,那么 Spring AOP 会选择使用 CGLIB 来动态代理目标类

    • CGLIB 的底层是通过 ASM 在运行时动态的生成目标类的一个子类。(还有其他相关类,主要是为增强调用时效率)会生成多个

    • 并且会重写父类所有的方法增强代码

    • 调用时先通过代理类进行增强,再直接调用父类对应的方法进行调用目标方法。从而实现 AOP

      • CGLIB 是通过继承的方法做的动态代理,因此如果某个类被标记为 final,那么它是无法使用 CGLIB 做动态代理的

      • CGLIB 除了生成目标子类代理类,还有一个 FastClass(路由类),可以(但不是必须)让本类方法调用进行增强,而不会像 JDK 代理那样本类方法调用增强会失效

  • JDK 和 CGLIB 的性能,JDK 动态代理生成类速度块,调用慢,CGLIB 生成类速度慢,但后续调用快,在老版本 CGLIB 的速度是 JDK 速度的 10 倍左右,但是实际上 JDK 的速度在版本升级的时候每次都提高很多性能,而 CGLIB 仍止步不前

    • 在对 JDK 动态代理与 CGLIB 动态代理的代码实验中看,1W 次执行下,JDK7 及 8 的动态代理性能比 CGLIB 要好 20% 左右

设计模式

Spring 源码用到了哪些设计模式

  1. 简单工厂-BeanFactory

  2. 工厂方法-FactoryBean

  3. 单例模式-Bean 实例

  4. 适配器模式-SpringMVC 中的 HandlerAdapter

  5. 装饰器模式-BeanWrapper

  6. 代理模式-AOP底层

  7. 观察者模式-Spring 的事件监听

  8. 策略模式-excludeFilters、includeFilters

  9. 模板方法模式-Spring 几乎所有的外接扩展都采用这种模式

  10. 责任链模式-AOP 的方法调用

0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区