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

作者:IT利刃出鞘 时间:2023-09-02 10:58:22 

简介

本文用示例介绍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的方法详解

来源:https://blog.csdn.net/feiying0canglang/article/details/124761970

标签:SpringBoot,容器,注册,bean
0
投稿

猜你喜欢

  • 浅谈Android性能优化之内存优化

    2023-08-19 04:36:43
  • java代理 jdk动态代理应用案列

    2023-02-17 10:08:55
  • JAVA面试题String产生了几个对象

    2023-03-19 20:46:21
  • Spring基于AspectJ的AOP开发案例解析

    2021-12-01 01:59:22
  • 深入HRESULT与Windows Error Codes的区别详解

    2023-10-16 15:19:42
  • 如何为Repository添加自定义方法

    2022-05-13 20:08:24
  • Android RxJava创建操作符Interval

    2023-08-14 01:26:24
  • SpringBoot 整合 Shiro 密码登录与邮件验证码登录功能(多 Realm 认证)

    2023-06-23 02:45:28
  • Spring注解配置IOC,DI的方法详解

    2023-10-18 14:06:23
  • 使用Flutter实现一个走马灯布局的示例代码

    2023-06-19 03:50:03
  • Java环境配置图文教程(推荐)

    2023-09-17 11:27:42
  • Java采用循环链表结构求解约瑟夫问题

    2022-07-27 16:35:59
  • C#实现收发邮件功能

    2021-09-20 19:40:46
  • C# TabControl控件中TabPage选项卡切换时的触发事件问题

    2022-10-30 08:11:13
  • 基于JavaSwing设计和实现的酒店管理系统

    2022-03-31 12:12:14
  • Java实现FTP上传到服务器

    2022-10-07 10:28:58
  • 浅析Java线程的中断机制

    2023-11-19 20:11:50
  • Java 异步编程实践_动力节点Java学院整理

    2023-06-18 17:04:12
  • 如何从Java接口的角度切入静态工厂模式

    2021-11-13 16:40:01
  • Java基于zxing生成二维码矩阵过程解析

    2023-11-23 06:04:06
  • asp之家 软件编程 m.aspxhome.com