当前位置 : 主页 > 编程语言 > java >

Spring容器注入bean的五种方法逐个解析

来源:互联网 收集:自由互联 发布时间:2023-03-17
目录 前言 @ComponentScan+@Component @Configuration+@Bean 通过@Import注解 1.直接导入类的class 2.导入配置类 3.导入ImportSelector的实现类 4.导入ImportBeanDefinitionRegistrar的实现类 借助FactoryBean接口 借助
目录
  • 前言
  • @ComponentScan+@Component
  • @Configuration+@Bean
  • 通过@Import注解
    • 1.直接导入类的class
    • 2.导入配置类
    • 3.导入ImportSelector的实现类
    • 4.导入ImportBeanDefinitionRegistrar的实现类
  • 借助FactoryBean接口
    • 借助BeanDefinitionRegistryPostProcessor接口

      前言

        我们在项目开发中都用到Spring,知道对象是交由Spring去管理。那么将一个对象加入到Spring容器中,有几种方法呢,我们来总结一下。

      @ComponentScan+@Component

        @ComponentScan可以放在启动类上,指定要扫描的包路径;该包路径下被@Component修饰的类,都会被注入到Spring容器中。

      import org.springframework.context.annotation.AnnotationConfigApplicationContext;
      import org.springframework.context.annotation.ComponentScan;
      @ComponentScan(basePackages = "com.gs.beanRegister")
      public class BootStrap {
          public static void main(String[] args) {
              AnnotationConfigApplicationContext context = 
              new AnnotationConfigApplicationContext(BootStrap.class);
              A bean = context.getBean(A.class);
              bean.say();
          }
      }
      

        com.gs.beanRegister包下:

      import org.springframework.stereotype.Component;
      @Component
      public class A {
          public void say() {
              System.out.println("这是a");
          }
      }
      

        注:在SpringBoot中,由于其自动装配的特性,所以@ComponentScan可以不加,只要@Component修饰的类和启动类在同一包下或者在启动类所在包的子包下。

      @Configuration+@Bean

        @Configuration用来声明一个配置类,如果它的方法被@Bean修饰,那么该方法返回的对象也会被注入到Spring容器中。

        代码方面,BootStrap 类不动,A类的@Component去掉,com.gs.beanRegister包下建个配置类:

      import org.springframework.context.annotation.Configuration;
      import org.springframework.context.annotation.Bean;
      @Configuration
      public class MyConfiguration {
          @Bean
          public A a() {
              return new A();
          }
      }
      

      通过@Import注解

        这个注解可能平时大家接触得不多,它有好几种使用方式。

      1.直接导入类的class

      import org.springframework.context.annotation.Import;
      import org.springframework.context.annotation.AnnotationConfigApplicationContext;
      @Import(A.class)
      public class BootStrap {
          public static void main(String[] args) {
              AnnotationConfigApplicationContext context = 
              new AnnotationConfigApplicationContext(BootStrap.class);
              A bean = context.getBean(A.class);
              //B bean = context.getBean(B.class);
              bean.say();
          }
      }
      

        A类不用添加任何注解:

      public class A {
          public void say() {
              System.out.println("这是a");
          }
      }
      

      2.导入配置类

      import org.springframework.context.annotation.AnnotationConfigApplicationContext;
      import org.springframework.context.annotation.Import;
      @Import(MyConfiguration.class)
      public class BootStrap {
          public static void main(String[] args) {
              AnnotationConfigApplicationContext context = 
              new AnnotationConfigApplicationContext(BootStrap.class);
              A bean = context.getBean(A.class);
              bean.say();
          }
      }
      
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      // 使用@Import导入配置类时,@Configuration可以不加
      //@Configuration
      public class MyConfiguration {
          @Bean
          public A a() {
              return new A();
          }
      }
      

      3.导入ImportSelector的实现类

      import org.springframework.context.annotation.AnnotationConfigApplicationContext;
      import org.springframework.context.annotation.Import;
      @Import(MyImportSelector.class)
      public class BootStrap {
          public static void main(String[] args) {
              AnnotationConfigApplicationContext context = 
              new AnnotationConfigApplicationContext(BootStrap.class);
              A bean = context.getBean(A.class);
              bean.say();
          }
      }
      
      import org.springframework.context.annotation.ImportSelector;
      import org.springframework.core.type.AnnotationMetadata;
      public class MyImportSelector implements ImportSelector {
          @Override
          public String[] selectImports(AnnotationMetadata metadata) {
              // 返回要注入的bean的全路径,A类不用任何注解修饰
              // SpringBoot的自动装配,就用到了这种方式:
              // 返回配置类的全路径,配置类的@Bean方法返回的对象也能注入到容器中
              return new String[] { A.class.getName() };
          }
      }
      

      4.导入ImportBeanDefinitionRegistrar的实现类

      import org.springframework.context.annotation.AnnotationConfigApplicationContext;
      import org.springframework.context.annotation.Import;
      @Import(MyImportBeanDefinitionRegistrar.class)
      public class BootStrap {
          public static void main(String[] args) {
              AnnotationConfigApplicationContext context = 
              new AnnotationConfigApplicationContext(BootStrap.class);
              A bean = context.getBean(A.class);
              bean.say();
          }
      }
      
      import org.springframework.beans.factory.config.BeanDefinition;
      import org.springframework.beans.factory.support.BeanDefinitionRegistry;
      import org.springframework.beans.factory.support.RootBeanDefinition;
      import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
      import org.springframework.core.type.AnnotationMetadata;
      public class MyImportBeanDefinitionRegistrar implements 
                   ImportBeanDefinitionRegistrar {
          @Override
          public void registerBeanDefinitions(AnnotationMetadata metadata, 
                      BeanDefinitionRegistry registry) {
              // 构建bean的元数据,A类不用任何注解修饰
              // spring-mybatis扫描mapper接口,生成代理类,就是用的这种方式
              BeanDefinition definition = new RootBeanDefinition(A.class);
              registry.registerBeanDefinition("a", definition);
          }
      }
      

      借助FactoryBean接口

        实现FactoryBean接口的类,除了本身会被注入外,getObject方法返回的对象也会被注入到Spring容器中。

      import org.springframework.context.annotation.AnnotationConfigApplicationContext;
      import org.springframework.context.annotation.Import;
      @Import(MyFactoryBean.class)
      public class BootStrap {
          public static void main(String[] args) {
              AnnotationConfigApplicationContext context = 
              new AnnotationConfigApplicationContext(BootStrap.class);
              A bean = context.getBean(A.class);
              bean.say();
          }
      }
      
      import org.springframework.beans.factory.FactoryBean;
      public class MyFactoryBean implements FactoryBean {
          @Override
          public Object getObject() throws Exception {
              return new A();
          }
          @Override
          public Class<?> getObjectType() {
              return A.class;
          }
      }
      

      借助BeanDefinitionRegistryPostProcessor接口

        在Spring容器启动时,会调用该接口的postProcessBeanDefinitionRegistry方法,大概意思是等BeanDefinition(上面提到的bean的元数据)加载完成后,再对它进行后置处理。所以可以在此调整BeanDefinition,从而把对应的bean注入。

      import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
      import org.springframework.context.annotation.AnnotationConfigApplicationContext;
      public class BootStrap {
          public static void main(String[] args) {
              AnnotationConfigApplicationContext context = 
              new AnnotationConfigApplicationContext();
              BeanDefinitionRegistryPostProcessor postProcessor = 
              new MyBeanDefinitionRegistryPostProcessor();
              context.addBeanFactoryPostProcessor(postProcessor);
              context.refresh();
              A a = context.getBean(A.class);
              a.say();
          }
      }
      
      import org.springframework.beans.BeansException;
      import org.springframework.beans.factory.config.BeanDefinition;
      import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
      import org.springframework.beans.factory.support.BeanDefinitionRegistry;
      import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
      import org.springframework.beans.factory.support.RootBeanDefinition;
      public class MyBeanDefinitionRegistryPostProcessor implements 
                   BeanDefinitionRegistryPostProcessor {
          @Override
          public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry 
                      registry) throws BeansException {
              BeanDefinition definition = new RootBeanDefinition(A.class);
              registry.registerBeanDefinition("a", definition);
          }
          @Override
          public void postProcessBeanFactory(ConfigurableListableBeanFactory 
                      beanFactory) throws BeansException {
          }
      }
      

      到此这篇关于Spring容器注入bean的五种方法逐个解析的文章就介绍到这了,更多相关Spring注入bean内容请搜索自由互联以前的文章或继续浏览下面的相关文章希望大家以后多多支持自由互联!

      上一篇:Spring&nbsp;IOC与DI核心深入理解
      下一篇:没有了
      网友评论