SpringBoot向容器注册bean的方法详解

 更新时间:2022年05月14日 11:00:51   作者:IT利刃出鞘  
这篇文章主要利用示例为大家详细介绍了SpringBoot如何向容器注册bean(即:将对象加入容器)的四种方法,文中的示例代码讲解详细,需要的可以参考一下

简介

本文用示例介绍SpringBoot如何向容器注册bean(即:将对象加入容器)。

法1:@Component

(@Controller/@Service/@Repository也可以,因为它里边包含@Component)

默认是加载和Application类所在同一个目录下的所有类,包括所有子目录下的类。

当启动类和@Component分开时,如果启动类在某个包下,需要在启动类中增加注解@ComponentScan,配置需要扫描的包名。例如:

@SpringBootApplication(scanBasePackages="com.test.chapter4")

此注解其实是@ComponentScan的basePackages,通过查看scanBasePackages即可得知。

@SpringBootApplication只会扫描@SpringBootApplication注解标记类包下及其子包的类,将这些类纳入到spring容器,只要类有@Component注解即可。

有的注解的定义中已加入@Component,所以这些注解也会被扫描到:@Controller,@Service,@Configuration,@Bean

@ComponentScan+@Configuration+@Component

DemoConfig在扫描路径之内

@Configuration
@ComponentScan(basePackages = { "com.example.demo.mybeans" })
public class DemoConfig {
}

 MyBean1在com.example.demo.mybeans下

@Component
public class MyBean1{
}

法2:@Configuration+@Bean

使用场景:将没有Component等注解的类导入。例如:第三方包里面的组件、将其他jar包中的类。

public class User {
    //@Value("Tom")
    public String username;
 
    public User(String s) {
        this.username = s;
    }
}
 
@Configuration
public class ImportConfig {
    @Bean
    public User user(){
        return new User("Lily");
    }
}
 
@RestController
public class ImportDemoController {
    @Autowired
    private User user;
 
    @RequestMapping("/importDemo")
    public String demo() throws Exception {
        String s = user.username;
        return "ImportDemo@SpringBoot " + s;
    }
}

法3:@Import等

简介

@Import(要导入到容器中的组件);容器会自动注册这个组件,id默认是全类名。(@Import是Spring的注解。)

ImportSelector:返回需要导入的组件的全类名数组;

ImportBeanDefinitionRegistrar:手动注册bean到容器中

@Import方式

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import({ImportDemoConfig.class})
public @interface EnableImportDemo {
}
 
public class ImportDemoConfig{
    @Bean
    public User user(){
        return new User("Lily");
    }
}
 
@EnableImportDemo
@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}
 
@RestController
public class ImportDemoController {
    @Autowired
    private User user;
 
    @RequestMapping("/importDemo")
    public String demo() {
        String s = user.getName();
        return "user.getName():" + s;
    }
}

ImportSelector方式

//自定义逻辑返回需要导入的组件
public class MyImportSelector implements ImportSelector {
 
    //返回值,就是到导入到容器中的组件全类名
    //AnnotationMetadata:当前标注@Import注解的类的所有注解信息
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        //当前类的所有注解
        Set<String> annotationTypes = importingClassMetadata.getAnnotationTypes();
        System.out.println("当前配置类的注解信息:"+annotationTypes);
        //注意不能返回null,不然会报NullPointException
        return new String[]{"com.paopaoedu.springboot.bean.user01","com.paopaoedu.springboot.bean.user02"};
    }
}
 
public class User01 {
	public String username;
 
    public User01() {
        System.out.println("user01...constructor");
    }
}
 
public class User02 {
    public String username;
 
    public User02() {
        System.out.println("user02...constructor");
    }
}
 
@Configuration
@Import({ImportDemo.class, MyImportSelector.class})
public class ImportConfig {
    @Bean
    public User user(){
        return new User("Lily");
    }
}
 
@RestController
public class ImportDemoController {
    @Autowired
    private User user;
 
    @Autowired
    private ImportDemo importDemo;
 
    @Autowired
    private User01 user01;
 
    @RequestMapping("/importDemo")
    public String demo() throws Exception {
        importDemo.doSomething();
        user01.username = "user01";
        String s = user.username;
        String s1 = user01.username;
 
        return "ImportDemo@SpringBoot " + s + " " + s1;
    }
}

ImportBeanDefinitionRegistrar方式

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    /**
     * AnnotationMetadata:当前类的注解信息
     * BeanDefinitionRegistry:BeanDefinition注册类;
     * 		把所有需要添加到容器中的bean;调用
     * 		BeanDefinitionRegistry.registerBeanDefinition手工注册进来
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
                   BeanDefinitionRegistry registry) {
 
        boolean definition = registry.containsBeanDefinition("com.paopaoedu.springboot.bean.User01");
        boolean definition2 = registry.containsBeanDefinition("com.paopaoedu.springboot.bean.User02");
        if(definition && definition2){
            //指定Bean定义信息作用域都可以在这里定义;(Bean的类型,Bean。。。)
            RootBeanDefinition beanDefinition = new RootBeanDefinition(User03.class);
            //注册一个Bean,指定bean名
            registry.registerBeanDefinition("User03", beanDefinition);
        }
    }
}
public class User03 {
    public String username;
 
    public User03() {
        System.out.println("user03...constructor");
    }
}

使用上和前面的类似就不举例了。

法4:FactoryBean

默认获取到的是工厂bean调用getObject创建的对象。

要获取工厂Bean本身,我们需要给id前面加一个&。例如:&xxxFactoryBean 注意类名是X,这里就是小写的x

public class UserFactoryBean implements FactoryBean<User04> {
    @Override
    public User04 getObject() throws Exception {
        // TODO Auto-generated method stub
        System.out.println("UserFactoryBean...getObject...");
        return new User04("User04");
    }
 
    @Override
    public Class<?> getObjectType() {
        // TODO Auto-generated method stub
        return User04.class;
    }
 
    //是否单例?
    //true:这个bean是单实例,在容器中保存一份
    //false:多实例,每次获取都会创建一个新的bean;
    @Override
    public boolean isSingleton() {
        return true;
    }
}
 
public class User04 {
    public String username;
    public User04(String s) {
        String nowtime= DateUtil.now();
        username=s+" "+nowtime;
    }
}
 
@Configuration
@Import({ImportDemo.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class ImportConfig {
 
    // 要获取工厂Bean本身,需要给id前面加一个&,&userFactoryBean
    @Bean
    public UserFactoryBean userFactoryBean(){
        return new UserFactoryBean();
    }
 
    @Bean
    public User user(){
        return new User("Lily");
    }
}
 
@RestController
public class ImportDemoController {
    @Autowired
    private User user;
 
    @Autowired
    private ImportDemo importDemo;
 
    @Autowired
    private User01 user01;
 
    @Autowired
    private UserFactoryBean userFactoryBean;
 
    @RequestMapping("/importDemo")
    public String demo() throws Exception {
        importDemo.doSomething();
        user01.username = "user01";
        String s = user.username;
        String s1 = user01.username;
        String s4 = userFactoryBean.getObject().username;
 
        return "ImportDemo@SpringBoot " + s + " " + s1 + " " + s4;
    }
}
 
@SpringBootApplication
public class SpringBootLearningApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(SpringBootLearningApplication.class, args);
 
        AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext("com.paopaoedu.springboot.config");
        ImportDemo importDemo = context.getBean(ImportDemo.class);
        importDemo.doSomething();
        printClassName(context);
 
        Object bean1 = context.getBean("userFactoryBean");
        Object bean2 = context.getBean("userFactoryBean");
        System.out.println(bean1 == bean2);
    }
 
    private static void printClassName(AnnotationConfigApplicationContext annotationConfigApplicationContext){
        String[] beanDefinitionNames = annotationConfigApplicationContext.getBeanDefinitionNames();
        for (int i = 0; i < beanDefinitionNames.length; i++) {
            System.out.println("匹配的类"+beanDefinitionNames[i]);
        }
    }
}

测试结果

以上就是SpringBoot向容器注册bean的方法详解的详细内容,更多关于SpringBoot注册bean的资料请关注脚本之家其它相关文章!

相关文章

  • Spring boot 处理大文件上传完整代码

    Spring boot 处理大文件上传完整代码

    这篇文章主要介绍了Spring boot 处理大文件上传,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-07-07
  • SpringCloud实战小贴士之Zuul的路径匹配

    SpringCloud实战小贴士之Zuul的路径匹配

    这篇文章主要介绍了SpringCloud实战小贴士之Zuul的路径匹配,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10
  • Java实现复制文件并命名的超简洁写法

    Java实现复制文件并命名的超简洁写法

    这篇文章主要介绍了Java实现复制文件并命名的超简洁写法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • Spring Data Jpa Mysql使用utf8mb4编码的示例代码

    Spring Data Jpa Mysql使用utf8mb4编码的示例代码

    这篇文章主要介绍了Spring Data Jpa Mysql使用utf8mb4编码的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-11-11
  • Java数据结构之链表详解

    Java数据结构之链表详解

    本篇文章我们将讲解一种新型的数据结构—链表,链表是一种使用广泛的通用数据结构,它可以用来作为实现栈,队列等数据结构的基础.文中有非常详细的介绍,需要的朋友可以参考下
    2021-05-05
  • Java微信小程序oss图片上传的实现方法

    Java微信小程序oss图片上传的实现方法

    这篇文章主要介绍了Java微信小程序oss图片上传的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12
  • 一篇文章轻松了解SpringBoot配置高级

    一篇文章轻松了解SpringBoot配置高级

    大家都知道SpringBoot拥有良好的基因,还能简化编码、配置、部署、监控,也是现在面试必问的一个点,下面这篇文章主要给大家介绍了如何通过一篇文章轻松了解SpringBoot配置高级的相关资料,需要的朋友可以参考下
    2022-11-11
  • SpringBoot的ConfigurationProperties或Value注解无效问题及解决

    SpringBoot的ConfigurationProperties或Value注解无效问题及解决

    在SpringBoot项目开发中,全局静态配置类读取application.yml或application.properties文件时,可能会遇到配置值始终为null的问题,这通常是因为在创建静态属性后,IDE自动生成的Get/Set方法包含了static关键字
    2024-11-11
  • Java实现XML文件学生通讯录

    Java实现XML文件学生通讯录

    这篇文章主要为大家详细介绍了Java实现XML文件学生通讯录,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-02-02
  • Geotools实现shape文件的写入功能

    Geotools实现shape文件的写入功能

    Geotools作为开源的Java GIS三方库,已经成为GIS服务器端的主流开源库,其功能非常强大,涉及到GIS业务的方方面面,其中就包括GIS数据的读写,今天小编就借助Geotools来实现shape数据的写入,需要的朋友可以参考下
    2023-08-08

最新评论