注册Bean,就是实例化将他交给容器管理,IoC 的核心思想是将对象的创建、生命周期管理以及对象之间的依赖关系管理从代码中转移到 Spring 容器中。当把一个 Bean 注册到 Spring 容器时。
一 依赖注入
这个对象的创建,我们可以不用Spring,我们自己来创建对象直接new出来一个对象。但是如果是一个非常复杂的工程,你一个对象需要依赖别的对象,你不能一个个都new出来,太耽误事了。实际上你可以通过依赖关系,交给Spring来生成依赖的bean。举个例子A依赖B,有了Spring的话,,容器会负责创建对象并将它们之间的依赖关系注入,这就是所谓的依赖注入。依赖注入的方式Spring提供了以下几种来管理方式对象之间的依赖关系:
(1)构造函数注入
import org.springframework.stereotype.Service;
@Service
public class SrvBService {
private final SrvBConfig srvBConfig;
// 构造函数注入
public SrvBService(SrvBConfig srvBConfig) {
this.srvBConfig = srvBConfig;
}
// 其他业务逻辑
public void doSomething() {
if (srvBConfig.isEnabled()) {
// 执行相关操作
}
}
}
(2)字段注入
这里的字段注入不是指@Component,而是 @Autowired,同样的还有@Resource 或 @Inject 等注解直接在类的字段上进行依赖注入。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class SrvBProcessor {
// 字段注入
@Autowired
private SrvBConfig srvBConfig;
public boolean isServiceEnabled() {
return srvBConfig.isEnabled();
}
}
(3)Setter 方法注入
使用 @Autowired 注解在 Setter 方法上,Spring 容器会调用该 Setter 方法将依赖对象注入。但是在Spring比较新的版本,如果对应的对象构造函数只有一个。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class SrvBManager {
private SrvBConfig srvBConfig;
// Setter 方法注入
@Autowired
public void setSrvBConfig(SrvBConfig srvBConfig) {
this.srvBConfig = srvBConfig;
}
public void checkConfig() {
if (srvBConfig.isEnabled()) {
// 处理逻辑
}
}
}
二 生命周期管理
在 Spring 框架里,控制反转(IoC)的生命周期管理指的是 Spring 容器对其所管理的 Bean 从创建、初始化、使用到销毁整个过程的全面管控。
实例化 —》 属性赋值 —》初始化 —》使用 —》 销毁
实例化你可以理解new一个出来。
你new出来,还要对里面赋值,同样前面的依赖注入,你可以把你依赖的别的对象在这个阶段注入进来赋值。
初始化,这个词很有迷惑性,实际是指Spring 会对 Bean 进行初始化操作。
使用,Bean 就可以被应用程序使用了。其他组件可以通过依赖注入的方式获取该 Bean 并调用其方法
当 Spring 容器关闭时,会对需要销毁的 Bean 进行清理操作
实例化
@Data
public class CommonConfig {
private String name = "config";
public CommonConfig() {
}
public CommonConfig(String name) {
this.name = name;
}
}
当使用 @Bean 注解注册 CommonConfig 时,Spring 会调用其构造函数创建实例。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CommonConfigConfiguration {
@Bean
public CommonConfig commonConfig() {
return new CommonConfig("defaultName");
}
}
属性赋值(Populate Properties)
实例化完成后,Spring 容器会将 Bean 依赖的其他 Bean 或配置属性注入到该 Bean 中,这一过程也被称为依赖注入。可以通过 @Autowired、@Resource 等注解实现。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class SrvBProcessor {
@Autowired
private SrvBConfig srvBConfig;
// 其他代码
}
初始化(Initialization)
在属性赋值完成后,Spring 会对 Bean 进行初始化操作。有多种方式可以定义初始化逻辑:
实现 InitializingBean 接口:实现 afterPropertiesSet 方法,Spring 会在属性赋值后调用该方法。
使用 @PostConstruct 注解:在方法上添加该注解,Spring 会在属性赋值后调用该方法。
在 @Bean 注解中指定初始化方法:通过 initMethod 属性指定初始化方法。
import javax.annotation.PostConstruct;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
@PostConstruct
public void init() {
// 初始化逻辑
System.out.println("MyBean 初始化完成");
}
}
使用(In Use)
经过前面的步骤,Bean 就可以被应用程序使用了。其他组件可以通过依赖注入的方式获取该 Bean 并调用其方法
销毁(Destruction)
当 Spring 容器关闭时,会对需要销毁的 Bean 进行清理操作。同样有多种方式可以定义销毁逻辑:
实现 DisposableBean 接口:实现 destroy 方法,Spring 会在容器关闭时调用该方法。
使用 @PreDestroy 注解:在方法上添加该注解,Spring 会在容器关闭时调用该方法。
在 @Bean 注解中指定销毁方法:通过 destroyMethod 属性指定销毁方法。
import javax.annotation.PreDestroy;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
@PreDestroy
public void destroy() {
// 销毁逻辑
System.out.println("MyBean 销毁完成");
}
}
Spring 的 IoC 生命周期管理通过对 Bean 的实例化、属性赋值、初始化、使用和销毁等阶段的管控,确保 Bean 能够按照预期的方式创建、使用和清理,提高了应用程序的可维护性和可扩展性。
三 说一下常见的Bean的实例化方式
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CustomConfig {
@Bean
public MyService myService() {
return new MyService();
}
}
@Component 的派生注解,@Service、@Repository、@Controller 等注解都是它的派生注解。Spring 容器在启动时会扫描被这些注解标记的类,自动创建这些类的实例并注册到容器中。
实例化方式
Spring 组件扫描机制会自动发现被 @Component 注解标记的类,并创建它们的实例。@Autowired 则负责将这些实例注入到需要的地方。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class MyController {
private final MyService myService;
@Autowired
public MyController(MyService myService) {
this.myService = myService;
}
}