Q&A:Spring


1.Spring

①Bean

什么是 Spring Bean?

Bean 指的就是那些被 IoC 容器所管理的对象。我们需要告诉 IoC 容器帮助我们管理哪些对象,通过配置来实现。配置方式可以是 XML 文件、注解或者 Java 配置类。

<bean id="book" class="com.jwt.ioc.Book">
  <property name="bname" value="Java入门到精通"></property>
  <property name="bauthor" value="小简"></property>
</bean>

❶简述 bean 的生命周期

Bean生命周期:从对象创建到对象销毁的过程

  • 1、通过构造器创建 bean 实例(无参数构造)
  • 2、为 bean 的属性设置值和对其他 bean 引用(调用set方法)
  • 3、调用 bean 的初始化的方法(需要进行配置初始化的方法)
  • 4、bean 可以使用了(对象获取到了)
  • 5、当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)

如果有bean后置处理器,则bean的生命周期有七种

  • 1、通过构造器创建 bean 实例(无参数构造)
  • 2、为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)
  • 3、把 bean 实例传递 bean 后置处理器的方法 postProcessBeforeInitialization
  • 4、调用 bean 的初始化的方法(需要进行配置初始化的方法)
  • 5、把 bean 实例传递 bean 后置处理器的方法 postProcessAfterInitialization
  • 6、bean 可以使用了(对象获取到了)
  • 7、当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)
  1. 实例化(通过反射创建对象)
  2. 属性填充(属性值非自动装配)
  3. 初始化(如数据源赋值、校验属性)
  4. 销毁(ioc容器销毁关闭,关闭数据源)

❷什么是 Spring 容器

spring容器是spring的核心,一切的spring bean都存储在spring容器内,并通过ioc进行管理

spring容器就是一个bean工厂(BeanFactory),应用中bean的实例化、获取、销毁都是由这个bean工厂管理的。

ApplicationContext接口用于完成容器的配置,初始化,管理bean。一个Spring容器就是某个实现ApplicationContext

接口的类的实例。也就是说,从代码层面,Spring容器其实就是一个ApplicationContext。Spring容器的作用我觉得

是实现了控制反转这种思想

❸Spring自动装配方式有哪些?

bean装配:指在Spring容器中把bean组装到一起,前提是容器需要知道bean的依赖关系

什么是自动装配:根据指定装配规则(属性名称或者属性类型),Spring容器能够自动注入相互合作的bean,这意味着容器不需要配置,能通过Bean工厂自动处理bean之间的协作。

Spring的自动装配有五种模式:

  • no:不进行自动装配,通过手工设置ref属性来进行装配bean。

  • byName:根据Bean的名字进行自动装配。

  • byType:根据Bean的类型进行自动装配。

  • constructor:类似于byType,不过是应用于构造器的参数,如果正好有一个Bean与构造器的参数类型相同则可以自动装配,否则会导致错误。

  • autodetect:如果有默认的构造器,则通过constructor的方式进行自动装配,否则使用byType的方式进行自动装配。

@Autowired 和 @Resource 的区别是什么?

  • @Autowired 是 Spring 提供的注解,@Resource 是 JDK 提供的注解。
  • Autowired 默认的注入方式为byType(根据类型进行匹配),@Resource默认注入方式为 byName(根据名称进行匹配)。
  • 当一个接口存在多个实现类的情况下,@Autowired@Resource都需要通过名称才能正确匹配到对应的 Bean。Autowired 可以通过 @Qualifier 注解来显式指定名称,@Resource可以通过 name 属性来显式指定名称。

举个例子,SmsService 接口有两个实现类: SmsServiceImpl1SmsServiceImpl2,且它们都已经被 Spring 容器所管理。

// 报错,无法匹配到 bean
@Autowired
private SmsService smsService;


// 正确注入 SmsServiceImpl1 对象对应的 bean
@Autowired
@Qualifier(value = "smsServiceImpl1")
private SmsService smsService;

---------------------------------------------------------------------------

// 报错,无法匹配到 bean
@Resource
private SmsService smsService;


// 正确注入 SmsServiceImpl1 对象对应的 bean(比较推荐这种方式)
@Resource(name = "smsServiceImpl1")
private SmsService smsService;

@Bean和@Component有什么区别?

  • @Component 注解用在类上,表明一个类会作为组件类,并告知Spring要为这个类创建bean,每个类对应一个 Bean。自动装配到 Spring 容器中

  • @Bean 注解用在方法上,表示这个方法会返回一个 Bean。@Bean 需要在配置类中使用,即类上需要加上@Configuration注解。

@Bean 注解更加灵活。当需要将第三方类装配到 Spring 容器中,因为没办法源代码上添加@Component注解,只能使用@Bean 注解的方式,当然也可以使用 xml 的方式。

@Bean注解使用示例:

@Component
public class UserServiceImpl {
    private String name = "Tom";
    public String getName() {
        return name;
    }
}

@Configuration
public class AppConfig {
    @Bean
    public UserService userService(){
        return new UserServiceImpl();
    }
}

上面的代码相当于下面的 xml 配置

<beans>
    <bean id="userService" class="com.test.UserServiceImpl"/>
</beans>

❹BeanFactory和FactoryBean的区别?

  • BeanFactory:管理Bean的容器,Spring中生成的Bean都是由这个接口的实现来管理的。

  • FactoryBean:通常是用来创建比较复杂的bean,一般的bean直接用xml配置即可,但如果一个bean的
    创建过程中涉及到很多其他的bean和复杂的逻辑,直接用xml配置比较麻烦,这时可以考虑用
    FactoryBean,可以隐藏实例化复杂Bean的细节。

❺BeanFactory和ApplicationContext有什么区别?

BeanFactory 和 ApplicationContext 是 Spring 的两大核心接口,都可以当做 Spring 的容器,管理Bean。其中
ApplicationContext是 BeanFactory的子接口。

1、功能上的区别

  • BeanFactory是Spring里面最底层的接口,包含了各种Bean的定义,读取bean配置文档,管理bean的加载、实例化,控制bean的生命周期,维护bean之间的依赖关系。

  • ApplicationContext接口作为BeanFactory的派生,除了提供BeanFactory所具有的功能外,还提供了更完整的框架功能,如继承MessageSource、支持国际化、统一的资源文件访问方式、同时加载多个配置文件等功能。

2、加载方式的区别

  • BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化。这样,我们就不能发现一些存在的Spring的配置问题。如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常。(懒汉思想生成Bean)
  • ApplicationContext是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误,这样有利于检查所依赖属性是否注入。ApplicationContext启动后预载入所有的单例Bean,那么在需要的时候,不需要等待创建bean,因为它们己经创建好了。(饿汉思想生成Bean)
  • 相对于基本的BeanFactory,ApplicationContext 唯一的不足是占用内存空间。当应用程序配置Bean较多
    时,程序启动较慢。

3、创建方式的区别

  • BeanFactory通常以编程的方式被创建
  • ApplicationContext还能以声明的方式创建,如使用ContextLoader。

4、注册方式的区别

  • BeanFactory 和 ApplicationContext 都支持 BeanPostProcessor、BeanFactoryPostProcessor 的使用,但两者之间的区别是:BeanFactory需要手动注册,ApplicationContext则是自动注册。

❻Spring中bean的作用域

作用域 作用范围 描述
singleton 所用spring应用 单例,Spring中的bean默认都是单例的。
prototype 所用spring应用 每次请求都会创建一个新的bean实例。即每次调用getBean()时,相当于执行newXxxBean()。
request spring web 应用 每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效。
session spring web 应用 每一次来自新 session 的 HTTP 请求都会产生一个新的 bean,该bean仅在当前HTTP session内有效。
application/global-session spring web 应用 全局session作用域,每个 Web 应用在启动时创建一个 Bean,该 bean 仅在当前应用启动时间内有效。
websocket spring web 应用 每一次 WebSocket 会话产生一个新的 bean。

配置 bean 的作用域呢?

xml 方式:

<bean id="..." class="..." scope="singleton"></bean>

注解方式:

@Bean
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public Person personPrototype() {
    return new Person();
}

❼Spring框架中的单例Bean是线程安全的么?

无状态bean:没有实例变量的bean,不能保存数据,是线程安全的。

有状态bean:有实例变量的bean,可以保存数据,是非线程安全的。

在Spring中无状态的Bean适合用单例模式,这样可以共享实例提高性能。有状态的Bean在多线程环境下

不安全,一般用 Prototype 模式或者使用 ThreadLocal 解决线程安全问题。

②IOC

  • 简述 Spring 的 IOC 机制

IoC(Inverse of Control:控制反转) :就是由Spring容器管理bean的整个生命周期,通过反射实现对其他对象的控制,包括初始化、创建、销毁等,解放手动创建对象的过程,同时降低类之间的耦合度。

IOC的好处就是降低了类之间的耦合,对象创建和初始化交给Spring容器管理,在需要的时候只需向容器进行申请。资源不由使用资源者管理,而由不使用资源的第三方管理,这可以带来很多好处。

第一,资源集中管理,实现资源的可配置和易管理。

第二,降低了使用资源双方的依赖程度,也就是我们说的耦合度。

IoC 的思想就是将原本在程序中手动创建对象的控制权,交由 Spring 框架来管理。

  • 控制 :指的是对象创建(实例化、管理)的权力
  • 反转 :控制权交给外部环境(Spring 框架、IoC 容器)
  • 什么是 DI 依赖注入?

IOC的一种实现方式就是依赖注入(DI)

依赖注入(Dependency Injection, DI):动态地向对象中注入它所需要的其他对象,原理是通过反射
注入的方式有 setter方法、构造器注入、注解自动注入(@Autowired、@Resource、@Value)

  • IOC容器初始化过程
  1. 从XML中读取配置文件。
  2. 将bean标签解析成 BeanDefinition,如解析 property 元素, 并注入到 BeanDefinition 实例中。
  3. 将 BeanDefinition 注册到容器 BeanDefinitionMap 中。
  4. BeanFactory 根据 BeanDefinition 的定义信息创建实例化和初始化 bean。

Spring依赖注入的方式有哪些

(1)构造器注入

(2)Setter方法注入

(3)注解注入

(4)接口注入

③AOP

简述 Spring AOP 的原理

④事务

Spring事务的实现方式和原理以及隔离级别?

spring事务传播机制

spring事务什么时候会失效?

⑤注解

简述 Spring 注解的实现原理

简述 Spring 的初始化流程

如何解决 Spring 的循环依赖问题

Spring 是怎么解析 JSON 数据的?

Spring 框架中都用到了哪些设计模式?

2.SpringMVC

  • Spring MVC 的原理和流程?
  • Spring MVC 如何处理一个请求?

3.SpringBoot

  • SpringBoot 是如何进行自动配置的?

4.注解

1. 声明bean

  • @Component:通用的注解,可标注任意类为 Spring 组件。

    • 如果一个 Bean 不知道属于哪个层,可以使用@Component 注解标注。
  • @Controller:对应 Spring MVC 控制层,即Controller层

  • @Service:对应服务层,即Service层

  • @Repository:对应持久层,即 Dao 层

2. 自动注入

@Autowired、@Resource、@Qualifier、@Value

  • @Autowired按照类型(ByType)注入,当一个接口存在多个实现类的情况下,用@Qualifier制定具体的名称
  • @Resource按照名称(ByName)注入,当一个接口存在多个实现类的情况下,用name属性指定具体的名称

3. 配置相关

@Configuration、@Bean、@ComponentScan(扫描Bean)

读取配置信息

AOP相关

@Aspect、@PointCut、@Before、@After、@Around

异步相关

@EnableAync、@Async

前后端传值

  • @PathVariable:用于获取路径参数。用于将路径参数数据映射到控制器方法的参数上

  • @RequestParam:用于获取查询参数。用于将请求参数区数据映射到控制器方法的的参数上


如果请求的 url 是:/user/007/info?userName=Tom

@GetMapping("/user/{userId}/info")
public List<Teacher> getIdAndName(
         @PathVariable("userId") Long userId,
         @RequestParam(value = "userName", required = false,defaultValue = "anonymous") String userName ) {
...
}

服务获取到的数据就是:userId=123456,userName=Tom

请求相关

  • @RequestMapping:映射请求url

  • @RequestParam:获取请求路径后面的参数值

  • @PathVariable:用于获取路径参数。

  • @RequestBody:获取请求体上的参数值

  • @ResponseBody:接口返回以json的形式

  • @RestController@Controller@ResponseBody的合集

异常处理相关

  • @ControllerAdvice:定义全局异常处理类
  • @ExceptionHandler:声明异常处理方法

参考

Sponsor❤️

您的支持是我不断前进的动力,如果您感觉本文对您有所帮助的话,可以考虑打赏一下本文,用以维持本博客的运营费用,拒绝白嫖,从你我做起!🥰🥰🥰

支付宝 微信

文章作者: 简简
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 简简 !
评论
填上邮箱会收到评论回复提醒哦!!!
 上一篇
SpringCloud-实用篇 SpringCloud-实用篇
实用篇包含微服务治理(注册发现,远程调用,配置管理,网关路由)、Docker技术、异步通信、分布式缓存、分布式搜索 小简从 0 开始学 Java 知识之 Java-学习路线 中的《SpringCloud-实用篇》,不定期更新所学笔记,期
2022-09-20
下一篇 
SpringBoot-整合篇 SpringBoot-整合篇
整合篇包含SpringBoot对各种第三方技术的整合。例如SQL、NoSQL、缓存、消息队列、定时任务、文档操作、认证授权、消息通知等等 小简从 0 开始学 Java 知识之 Java-学习路线 中的《SpringBoot-整合篇》,不
2022-09-15
  目录