Bean的作用域与生命周期(重要)
1. Bean的作用域
单例:singleton(默认值)
- Spring环境中,在创建IOC容器对象时,Spring创建目标对象
多例:prototype
- Spring环境中,在getBean()方法调用时,Spring创建目标对象
| 取值 | 含义 | 创建对象的时机 | 默认值 |
|---|---|---|---|
| singleton | 在 IOC 容器中,这个 bean 的对象始终为单实例 | IOC 容器初始化时 | 是 |
| prototype | 这个 bean 在 IOC 容器中有多个实例 | 获取 bean 时 | 否 |
| 取值 | 含义 | 创建对象的时机 | 默认值 |
|---|---|---|---|
| request | 请求范围内有效的实例 | 每次请求 | 否 |
| session | 会话范围内有效的实例 | 每次会话 | 否 |
2. Bean的生命周期
阶段一:加载Bean定义(加载配置信息)
阶段二:实例化Bean组件
阶段三:设置Bean属性
阶段四:调用Bean的初始化方法(@Bean注解中设置初始化方法(initMethod = "initStudent")才能有效)
阶段五:Bean可以使用
阶段六:调用Bean的销毁方法阶段(@Bean注解中设置初始化方法(destroyMethod = "destroyStudent")才能有效)
package com.mytest.bean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Student {
private Integer id;
@Value("张三")
private String name;
@Value("18")
private Integer age;
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
public Integer getId() {
return id;
}
@Value("1001")
public void setId(Integer id) {
System.out.println("2.setXXX()");
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Student() {
System.out.println("==>1.Student对象创建啦!!!");
}
public Student(Integer id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
//初始化方法
public void initStudent(){
System.out.println("3. 初始化....");
}
//销毁方法
public void destroyStudent(){
System.out.println("5. 销毁....");
}
}
package com.mytest.config;
import com.mytest.bean.Student;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
@Configuration
public class SpringConfig {
//将student1对象,装配到IOC容器中
@Bean(value = "student1",initMethod = "initStudent",destroyMethod = "destroyStudent")
@Scope("singleton")
// @Scope("prototype")
public Student getStudent() {
return new Student(1, "张三", 20);
}
}
@Test
void contextLoads() {
//创建IOC容器对象
ConfigurableApplicationContext ioc = new AnnotationConfigApplicationContext(SpringConfig.class);
//从IOC容器对象中,获取Student对象
Student student = ioc.getBean(Student.class);
// Student student1 = ioc.getBean(Student.class);
// System.out.println("(student1==student) = " + (student1==student));
System.out.println("4. student = " + student);
//关闭容器对象时,销毁Student对象(Springboot中自动关闭容器对象)
ioc.close();
}
@Import与@Conditional(了解)注解
1. @Import
1.1 导入其他配置类
-
导入其他配置类:通过
@Import注解,你可以将一个或多个配置类导入到当前的配置中,使得这些配置类中的bean定义和配置能够被当前应用上下文识别。 -
案例代码
@Test
public void testImport(){
//创建IOC容器对象
ConfigurableApplicationContext ioc = new AnnotationConfigApplicationContext(CatConfig.class);
// ConfigurableApplicationContext ioc2 = new AnnotationConfigApplicationContext(DogConfig.class);
Cat cat = ioc.getBean(Cat.class);
System.out.println("cat = " + cat);
Dog dog = ioc.getBean(Dog.class);
System.out.println("dog = " + dog);
}
1.2 ImportSelector
-
引入实现
ImportSelector或ImportBeanDefinitionRegistrar接口的类**:这允许你在导入时动态决定哪些bean应该被注册到Spring容器中。 -
案例代码
package com.mytest.config; import org.springframework.context.annotation.ImportSelector; import org.springframework.core.type.AnnotationMetadata; public class MyImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { // 根据条件返回需要导入的配置类名称 // String[] strings = new String[]; // if(){ // strings[0] = "com.mytest.config.CatConfig"; // }else if(){ // strings[1] = "com.mytest.config.DogConfig"; // } return new String[] { "com.mytest.config.DogConfig" }; } }package com.mytest.config; import com.mytest.bean.Cat; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @Configuration //@Import(DogConfig.class) //导入配置类:DogConfig(将配置类中IOC容器的对象导入到当前配置类) @Import(MyImportSelector.class) public class CatConfig { @Bean("cat") public Cat getCat() { return new Cat(); } }
2 @Conditional
@Conditional注解
- 作用:它允许根据特定的条件来决定是否应该创建一个bean并装配到IOC容器中
- 应用:
@Conditional需要与实现了Condition接口的类一起使用。Condition接口只有一个方法matches(),该方法返回一个布尔值,指示条件是否匹配。如果返回true,则创建Bean或应用配置;如果返回false,则跳过。
-
案例代码
package com.mytest.mycondition; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; public class MyCondition implements Condition { /** * 判断是否装配对象 * false:不装配 * true:装配 */ @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { //.... return true; } }package com.mytest.config; import com.mytest.bean.Cat; import com.mytest.mycondition.MyCondition; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @Configuration //@Import(DogConfig.class) //导入配置类:DogConfig(将配置类中IOC容器的对象导入到当前配置类) @Import(MyImportSelector.class) public class CatConfig { @Bean("cat") @Conditional(MyCondition.class) //MyCondition类中的matches()返回true时,装配对象.返回false时,不装配对象 public Cat getCat() { return new Cat(); } }
BeanFactory与FactoryBean区别
区别:
| 特性 | FactoryBean | BeanFactory |
|---|---|---|
| 角色 | 定义如何创建一个特定类型的bean | 管理bean的生命周期和依赖关系 |
| 主要用途 | 控制bean创建逻辑,例如返回代理对象 | 提供bean的获取、管理和生命周期管理 |
| 接口实现 | 实现者提供具体的bean创建逻辑 | Spring容器的基础接口,用于管理bean生命周期 |
| 使用频率 | 较少使用,主要用于特殊需求 | 底层API,广泛应用于Spring内部 |
| 性能 | 可能涉及额外的创建逻辑,影响不大 | 更高效,因为它是轻量级的 |
| 高级特性 | 不提供额外的企业级特性 | 不提供额外的企业级特性 |
-
FactoryBean案例
package com.mytest.factorybean; import com.mytest.bean.Student; import org.springframework.beans.factory.FactoryBean; import org.springframework.stereotype.Component; //@Component("myFactoryBean") @Component("stu") public class MyFactoryBean implements FactoryBean<Student> { @Override public Student getObject() throws Exception { Student student = new Student(); student.setId(1111); student.setName("admin"); student.setAge(188); return student; } @Override public Class<?> getObjectType() { return Student.class; } @Override public boolean isSingleton() { return true; } }
//测试FactoryBean
@Test
public void testFactoryBean(){
ApplicationContext ioc = new AnnotationConfigApplicationContext(SpringConfig.class);
Student student = ioc.getBean("stu", Student.class);
System.out.println("student = " + student);
}