Java学习--Spring框架相关问题

Huang Zhiwei

Spring IoC

IoC(Inversion of Control:控制反转) 是一种设计思想,而不是一个具体的技术实现。IoC 的思想就是将原本在程序中手动创建对象的控制权,交由 Spring 框架来管理。 IoC 容器就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的。

  1. 对象之间的耦合度或者说依赖程度降低;
  2. 资源变的容易管理;比如你用 Spring 容器提供的话很容易就可以实现一个单例。

Spring IOC 的工作流程

大致可以分为两个阶段:

第一个阶段,就是 IOC 容器的初始化,这个阶段主要是根据程序中定义的 XML 或者注解等 Bean 的声明方式,通过解析和加载后生成 BeanDefinition,然后把 BeanDefinition 注册到 IOC 容器。通过注解或者 xml 声明的 bean 都会解析得到一个 BeanDefinition 实体,实体中包含这个 bean 中定义的基本属性。最后把这个 BeanDefinition 保存到一个 Map 集合里面,从而完成了 IOC 的初始化。IoC 容器的作用就是对这些注册的 Bean 的定义信息进行处理和维护。

第二个阶段,完成 Bean 初始化及依赖注入,可以分两种情况,通过反射对没有设置 lazy-init 属性的单例 bean 进行初始化,完成 Bean 的依赖注入。针对设置 layy-init 属性以及非单例 bean 的实例化,是在每次获取 bean对象的时候,调用 bean 的初始化方法来完成实例化的,并且 Spring IOC 容器不会去管理这些 Bean。

第三个阶段,Bean 的使用,会通过@Autowired或者BeanFactory.getBean()从IOC容器中获取指定的 bean 实例。

Spring Aop

Bean

Bean的声明

Bean 代指的就是那些被 IoC 容器所管理的对象,可以通过注解或者xml文件配置。

1
2
3
4
<!-- Constructor-arg with 'value' attribute -->
<bean id="..." class="...">
<constructor-arg value="..."/>
</bean>

@Component :通用的注解,可标注任意类为 Spring 组件。如果一个 Bean 不知道属于哪个层,可以使用@Component 注解标注。

@Repository : 对应持久层即 Dao 层,主要用于数据库相关操作。

@Service : 对应服务层,主要涉及一些复杂的逻辑,需要用到 Dao 层。

@Controller : 对应 Spring MVC 控制层,主要用于接受用户请求并调用 Service 层返回数据给前端页面。

@Configuration :注解声明配置类。

@Import :导入配置类或者普通的 Bean。

@Component 和 @Bean 的区别

  • @Component 注解作用于类,而@Bean注解作用于方法。
  • @Component通常是通过类路径扫描来自动侦测以及自动装配到 Spring 容器中,可以通过 @ComponentScan 注解定义要扫描的路径。@Bean 注解通常是在标有该注解的方法中定义产生这个 bean,@Bean告诉了 Spring 这是某个类的实例,当我需要用它的时候还给我。
  • @Bean 注解比 @Component 注解的自定义性更强,而且很多地方我们只能通过 @Bean 注解来注册 bean。比如当我们引用第三方库中的类需要装配到 Spring容器时,则只能通过 @Bean来实现。

@Autowired 和 @Resource 的区别

  • 两者都是注入bean的注解,Autowired 属于 Spring 内置的注解,默认butype,但当一个接口存在多个实现类的话,byType这种方式就无法正确注入对象了,这种情况下,注入方式会变为 byName(根据名称进行匹配),这个名称通常就是类名(首字母小写)。
  • @Resource属于 JDK 提供的注解,默认注入方式为 byName。如果无法通过名称匹配到对应的 Bean 的话,注入方式会变为byType
  • 通过 @Qualifier 注解来显式指定名称而不是依赖变量的名称。

单例 Bean 的线程安全问题

单例 Bean 存在线程问题,主要是因为当多个线程操作同一个对象的时候是存在资源竞争的,应对方法有以下两点:

  • 在 Bean 中尽量避免定义可变的成员变量;
  • 在类中定义一个 ThreadLocal 成员变量,将需要的可变成员变量保存在 ThreadLocal 中。

Bean 的生命周期

  • 从配置文件中找到bean的定义,利用Java Reflection API 创建bean实例;
  • 涉及属性的用set方法设置属性,setBeanName()、setBeanClassLoader()方法传入bean名字、classloader对象实例;
  • 调用 setBeanFactory()方法,传入 BeanFactory对象的实例;
  • 执行前置处理,postProcessBeforeInitialization() 方法;
  • 执行afterPropertiesSet()方法;
  • 如果 Bean 在配置文件中的定义包含 init-method 属性,执行指定的方法;
  • 标题: Java学习--Spring框架相关问题
  • 作者: Huang Zhiwei
  • 创建于: 2023-04-26 20:19:04
  • 更新于: 2023-09-02 23:05:46
  • 链接: https://huangzhw0221.github.io/2023/04/26/Java-Spring框架/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
 评论
此页目录
Java学习--Spring框架相关问题