Spring框架【java全端课29-下】

57 阅读4分钟

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

  • 引入实现ImportSelectorImportBeanDefinitionRegistrar接口的类**:这允许你在导入时动态决定哪些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区别

区别:

特性FactoryBeanBeanFactory
角色定义如何创建一个特定类型的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);

}