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 {
 
    }
}
相关推荐
不倒翁玩偶12 小时前
IDEA导入新的SpringBoot项目没有启动按钮
java·spring boot·intellij-idea
Elieal14 小时前
SpringBoot 数据层开发与企业信息管理系统实战
java·spring boot·后端
识君啊14 小时前
MyBatis-Plus 逻辑删除导致唯一索引冲突的解决方案
java·spring boot·mybatis·mybatis-plus·唯一索引·逻辑删除
Coder_Boy_14 小时前
Java开发者破局指南:跳出内卷,借AI赋能,搭建系统化知识体系
java·开发语言·人工智能·spring boot·后端·spring
Aric_Jones14 小时前
idea使用.env运行SpringBoot项目
java·spring boot·intellij-idea
代码栈上的思考15 小时前
SpringBoot 拦截器
java·spring boot·spring
jbtianci15 小时前
Spring Boot管理用户数据
java·spring boot·后端
编程彩机15 小时前
互联网大厂Java面试:从Jakarta EE到微服务架构的技术场景深度解读
spring boot·分布式事务·微服务架构·java面试·jakarta ee
biyezuopinvip16 小时前
基于Spring Boot的企业网盘的设计与实现(毕业论文)
java·spring boot·vue·毕业设计·论文·毕业论文·企业网盘的设计与实现
szhf7816 小时前
SpringBoot Test详解
spring boot·后端·log4j