SpringBoot-将Bean放入容器的五种方式

1、@Configuration + @Bean

复制代码
@Configuration
public class MyConfiguration {
    @Bean
    public Person person() {
        Person person = new Person();
        person.setName("spring");
        return person;
    }
}

2、@Componet + @ComponentScan

复制代码
@Component
public class Person {
    private String name;
 
    public String getName() {
 
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}
 
@ComponentScan(basePackages = "com.springboot.initbean.*")
public class Demo1 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class);
        Person bean = applicationContext.getBean(Person.class);
        System.out.println(bean);
    }
}

3、@Import注解导入

@import注解源码

复制代码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
 
    /**   * 用于导入一个class文件     * {@link Configuration @Configuration}, {@link ImportSelector},     * {@link ImportBeanDefinitionRegistrar}, or regular component classes to import.     */
    Class<?>[] value();
 
}

3.1、直接使用@import注解导入类

然后自动的就被放置在IOC容器中了。

复制代码
public class Person {
    private String name;
 
    public String getName() {
 
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}
/*** 直接使用@Import导入person类,然后尝试从applicationContext中取,成功拿到**/
@Import(Person.class)
public class Demo1 {
 
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class);
        Person bean = applicationContext.getBean(Person.class);
        System.out.println(bean);
    }
}

3.2 @Import + ImportSelector

复制代码
@Import(MyImportSelector.class)
public class Demo1 { 
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class);
        Person bean = applicationContext.getBean(Person.class);
        System.out.println(bean);
    }
}
 
class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.springboot.pojo.Person"};
    }
}

3.3 @Import + ImportBeanDefinitionRegistrar

bean的定义(bean的元数据),也是需要放在IOC容器中进行管理的,先有bean的元数据,

applicationContext再根据bean的元数据去创建Bean。

复制代码
@Import(MyImportBeanDefinitionRegistrar.class)
public class Demo1 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class);
        Person bean = applicationContext.getBean(Person.class);
        System.out.println(bean);
    }
}
 
class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
 
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        // 构建一个beanDefinition, 关于beanDefinition我后续会介绍,可以简单理解为bean的定义.
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Person.class).getBeanDefinition();
        // 将beanDefinition注册到Ioc容器中.
        registry.registerBeanDefinition("person", beanDefinition);
    }
}

3.4 @Import + DeferredImportSelector

DeferredImportSelector 它是 ImportSelector 的子接口,所以实现的方法和第二种无异。

只是Spring的处理方式不同,它和Spring Boot中的自动导入配置文件 延迟导入有关

复制代码
@Import(MyDeferredImportSelector.class)
public class Demo1 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class);
        Person bean = applicationContext.getBean(Person.class);
        System.out.println(bean);
    }
}
class MyDeferredImportSelector implements DeferredImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        // 也是直接将Person的全限定名放进去
        return new String[]{Person.class.getName()};
    }
}

4、使用FactoryBean接口

FactoryBean, 后缀为bean,那么它其实就是一个bean,

BeanFactory,顾名思义 bean工厂,它是IOC容器的顶级接口

复制代码
@Configuration
public class Demo1 {
    @Bean
    public PersonFactoryBean personFactoryBean() {
        return new PersonFactoryBean();
    }
 
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class);
        Person bean = applicationContext.getBean(Person.class);
        System.out.println(bean);
    }
}
 
class PersonFactoryBean implements FactoryBean<Person> {
 
    /**     *  直接new出来Person进行返回.     */
    @Override
    public Person getObject() throws Exception {
        return new Person();
    }
    /**     *  指定返回bean的类型.     */
    @Override
    public Class<?> getObjectType() {
        return Person.class;
    }
}

5、使用 BeanDefinitionRegistryPostProcessor

等beanDefinition加载完毕之后,对beanDefinition进行后置处理,

可以在此进行调整IOC容器中的beanDefinition,从而干扰到后面进行初始化bean。

复制代码
public class Demo1 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        MyBeanDefinitionRegistryPostProcessor beanDefinitionRegistryPostProcessor = new MyBeanDefinitionRegistryPostProcessor();
        applicationContext.addBeanFactoryPostProcessor(beanDefinitionRegistryPostProcessor);
        applicationContext.refresh();
        Person bean = applicationContext.getBean(Person.class);
        System.out.println(bean);
    }
}
 
class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
 
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Person.class).getBeanDefinition();
        registry.registerBeanDefinition("person", beanDefinition);
    }
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
 
    }
}
相关推荐
谢亮_vipxieliang17 小时前
Spring 事务失效的常见场景
java·开发语言·数据库·spring boot
专业程序开发源18 小时前
springboot简历管理系统81389-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·spring·php·课程设计
专业程序开发源18 小时前
springboot社区养老系统44071-计算机课程设计、毕业设计
vue.js·spring boot·后端·python·django·php·课程设计
余槐i19 小时前
数据没回滚也不报错:@Transactional 自调用失效的 3 种复现与修复
spring boot·mysql·多线程·spring 事务
小蒜学长19 小时前
基于SpringBoot的佳新超市管理系统设计与实现系统(代码+数据库+LW)
java·数据库·spring boot·后端·佳新超市管理系统
vx_Biye_Design21 小时前
springboot高校选课系统82776-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·spring·课程设计·express
专业程序开发源1 天前
SSM校园拍摄交流服务平台36936-计算机课程设计、毕业设计
java·spring boot·后端·python·elasticsearch·php·课程设计
AI人工智能+电脑小能手1 天前
Java 企业级工具类全家桶-74-JSON序列化工具类
spring boot·jackson·jdk 17·objectmapper·java工具类·json序列化·dto互转
ZealSinger1 天前
Boot4升级PostConstruct不跑了
java·spring boot·spring·升级迁移
专业程序开发源1 天前
django新闻推荐系统70655-计算机课程设计、毕业设计
java·javascript·spring boot·后端·python·django·课程设计