Springboot import注解的三种方式把Bean注入容器

在前面的博客中我们讲解到使用方法级别注解(@Bean)和类级别注解(@Controller、@Component、@Service等)加包扫描的方式注入Beans,这些方式的最后一步都要加载配置类。这篇博客我们来讲解使用import方式手动注入Bean的三种方式。

这里为了方便,导入了Springboot模块自动扫描注解,从而避免加载配置类。

第一种方式:@Import注解注入Bean

代码示例:

import com.michael.annotation.demo.POJO.Person;
import com.michael.annotation.demo.POJO.Student;
import org.springframework.context.annotation.*;

@Configuration
@Import({Student.class})
public class MyConfig {
    @Bean
    public Person person(){
        return new Person("Michael", 19);
    }
}

这里@Import注解在被@Configuration注解的配置类上;注解的value为数组类型,说明可以使用这种方法注入多个Beans.

  • 配置测试代码
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;

import static java.lang.System.out;
@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        ApplicationContext applicationContext = SpringApplication.run(DemoApplication.class, args);

         for(String name : applicationContext.getBeanDefinitionNames()){
            out.println(name);
        }
    }
}
  • 输出:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
demoApplication
org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory
test
myConfig
personService
com.michael.annotation.demo.POJO.Student
person
org.springframework.boot.autoconfigure.AutoConfigurationPackages
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration
propertySourcesPlaceholderConfigurer
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration$ClassProxyingConfiguration
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration
org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor
org.springframework.boot.context.internalConfigurationPropertiesBinderFactory
org.springframework.boot.context.internalConfigurationPropertiesBinder
org.springframework.boot.context.properties.ConfigurationPropertiesBeanDefinitionValidator
org.springframework.boot.context.properties.ConfigurationBeanFactoryMetadata
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration
spring.info-org.springframework.boot.autoconfigure.info.ProjectInfoProperties
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration
taskExecutorBuilder
applicationTaskExecutor
spring.task.execution-org.springframework.boot.autoconfigure.task.TaskExecutionProperties
org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration
taskSchedulerBuilder
spring.task.scheduling-org.springframework.boot.autoconfigure.task.TaskSchedulingProperties
org.springframework.aop.config.internalAutoProxyCreator
  • 从输出可以发现,Student类型的Bean被注入到了容器里,并且ID为带全类名。

  • 这里我们测试一下当@Import单独使用时,它是否能生效。首先注释MyConfig类的@Import,再创建MyConfig2类并注解@Import。

package com.michael.annotation.demo.configuration;

import com.michael.annotation.demo.POJO.Student;
import org.springframework.context.annotation.Import;

@Import({Student.class})
public class MyConfig2 {
}
  • 输出:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
demoApplication
org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory
test
myConfig
personService
person
org.springframework.boot.autoconfigure.AutoConfigurationPackages
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration
propertySourcesPlaceholderConfigurer
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration$ClassProxyingConfiguration
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration
org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor
org.springframework.boot.context.internalConfigurationPropertiesBinderFactory
org.springframework.boot.context.internalConfigurationPropertiesBinder
org.springframework.boot.context.properties.ConfigurationPropertiesBeanDefinitionValidator
org.springframework.boot.context.properties.ConfigurationBeanFactoryMetadata
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration
spring.info-org.springframework.boot.autoconfigure.info.ProjectInfoProperties
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration
taskExecutorBuilder
applicationTaskExecutor
spring.task.execution-org.springframework.boot.autoconfigure.task.TaskExecutionProperties
org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration
taskSchedulerBuilder
spring.task.scheduling-org.springframework.boot.autoconfigure.task.TaskSchedulingProperties
org.springframework.aop.config.internalAutoProxyCreator
  • 输出没有Student类型的Bean,说明@Import注解需要和@Configuration结合使用才能生效。

实现ImportSelector接口的类并把对应Clazz实例当做value放入@Import

  • 实现ImportSelector接口的类:
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        //返回值为String数组类型,实际值应该是注入Bean类的全类名。
        return new String[]{"com.michael.annotation.demo.POJO.Lecturer"};
    }
}

我们可以看到实现的方法中还有一个对象参数annotationMetadata;可以从该对象中获取配置类的其他注解的信息,可用于做出其他业务逻辑的判断。实现方法的返回值为数组类型,实际值应该为注入Bean类的全类名。

  • 把该类对应的运行时Clazz对象当做value放入@Import注解:
@Configuration
@Import({Student.class, MyImportSelector.class})
public class MyConfig {
    @Bean
    public Person person(){
        return new Person("Michael", 19);
    }
}
  • 输出结果:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
demoApplication
org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory
test
myConfig
personService
com.michael.annotation.demo.POJO.Student
com.michael.annotation.demo.POJO.Lecturer
person
org.springframework.boot.autoconfigure.AutoConfigurationPackages
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration
propertySourcesPlaceholderConfigurer
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration$ClassProxyingConfiguration
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration
org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor
org.springframework.boot.context.internalConfigurationPropertiesBinderFactory
org.springframework.boot.context.internalConfigurationPropertiesBinder
org.springframework.boot.context.properties.ConfigurationPropertiesBeanDefinitionValidator
org.springframework.boot.context.properties.ConfigurationBeanFactoryMetadata
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration
spring.info-org.springframework.boot.autoconfigure.info.ProjectInfoProperties
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration
taskExecutorBuilder
applicationTaskExecutor
spring.task.execution-org.springframework.boot.autoconfigure.task.TaskExecutionProperties
org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration
taskSchedulerBuilder
spring.task.scheduling-org.springframework.boot.autoconfigure.task.TaskSchedulingProperties
org.springframework.aop.config.internalAutoProxyCreator
  • 输出显示,Lecture类的实例被注入到容器中,Bean的ID为类的全类名。

实现ImportBeanDefinitionRegistrar接口的类并把对应Clazz实例当做value放入@Import

  • 实现ImportBeanDefinitionRegistrar接口的类:
import com.michael.annotation.demo.POJO.Class;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.type.AnnotationMetadata;

public class MyImportBeanDefinitionRegistrar implements org.springframework.context.annotation.ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //可以从importingClassMetadata和registry对象获取一些上下文信息进行其他业务逻辑的判断
        boolean b1 = registry.containsBeanDefinition("com.michael.annotation.demo.POJO.Student");
        boolean b2 = registry.containsBeanDefinition("com.michael.annotation.demo.POJO.Lecturer");

        if(b1 && b2){
            registry.registerBeanDefinition("Class", new RootBeanDefinition(Class.class));
        }
    }
}

我们可以从重写方法的importingClassMetadata和registry对象参数中获s取其他上下文信息进行其他业务逻辑的判断;这里做了一个简单的业务判断,如果容器中存在Student和Lecture实例就注入Class类型的Bean。其实这里还有其他方式注入Bean,可以通过观察对象参数回溯到源代码,举一反三。

  • 把该类对应的运行时Clazz对象当做value放入@Import注解:
import com.michael.annotation.demo.POJO.Person;
import com.michael.annotation.demo.POJO.Student;
import org.springframework.context.annotation.*;

@Configuration
@Import({Student.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MyConfig {
    @Bean
    public Person person(){
        return new Person("Michael", 19);
    }
}
  • 输出结果:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
demoApplication
org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory
test
myConfig
personService
com.michael.annotation.demo.POJO.Student
com.michael.annotation.demo.POJO.Lecturer
person
Class
org.springframework.boot.autoconfigure.AutoConfigurationPackages
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration
propertySourcesPlaceholderConfigurer
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration$ClassProxyingConfiguration
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration
org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor
org.springframework.boot.context.internalConfigurationPropertiesBinderFactory
org.springframework.boot.context.internalConfigurationPropertiesBinder
org.springframework.boot.context.properties.ConfigurationPropertiesBeanDefinitionValidator
org.springframework.boot.context.properties.ConfigurationBeanFactoryMetadata
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration
spring.info-org.springframework.boot.autoconfigure.info.ProjectInfoProperties
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration
taskExecutorBuilder
applicationTaskExecutor
spring.task.execution-org.springframework.boot.autoconfigure.task.TaskExecutionProperties
org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration
taskSchedulerBuilder
spring.task.scheduling-org.springframework.boot.autoconfigure.task.TaskSchedulingProperties
org.springframework.aop.config.internalAutoProxyCreator
  • 观察输出,可以看到ID为"Class"实例被注入到了容器中。
发布了70 篇原创文章 · 获赞 4 · 访问量 3031

猜你喜欢

转载自blog.csdn.net/qq_34515959/article/details/105060889