通过Spring注解注册Bean的四种方式

文章目录

        • 包扫描+组件标注注解
        • @Bean注解
        • @Import注解
        • 使用FactoryBean(工厂Bean)

给spring容器中注册bean有四种通过注解的方式:

  1. 包扫描+组件标注注解
  2. @Bean
  3. @Import
  4. 使用FactoryBean(工厂Bean)

下面逐个介绍他们的用法:

包扫描+组件标注注解

这种方式使我们最为常见的一种,通过两类注解配合使用。

@ComponentScan注解用来标在配置类的上方,表示了需要对哪些包进行扫描。也可以通过excludeFilters属性来指明那些类型是不被扫描的组件。

第二类注解是指@Controller/@Service/@Repository/@Component四个中的一个,这些注解一般标在自己写的类的上方,表示他们是需要注册到spring容器中的。

@Bean注解

有时候我们需要将一些类,不属于我们编写的类注册进spring容器当中,这时候我们不能再通过上面那种方式,而是需要在注解类中的方法上面加上@Bean注解,这样就会将该方法所返回的对象注册进spring容器当中。

spring中注册时实例默认是单实例的,即singleton。在ioc容器启动会调用方法创建对象放到ioc容器中。以后每次获取就是直接从容器(map.get())中拿。

当我们在@Bean注解相同位置再添加一个@Scope(“prototype”)注解时,它表示Bean是多实例的:ioc容器启动并不会去调用方法创建对象放在容器中。每次获取的时候才会调用方法创建对象。

当然,我们也可以通过@Lazy注解加在@Bean注解相同位置来表示懒加载,这样即使是默认情况下的单例,容器启动的时候创建对象,也会变成容器启动不创建对象。第一次使用(获取)Bean创建对象,并初始化。

@Import注解

@Import注解使用时直接标注在配置类的上方,表示向Spring容器中注册哪些Bean。其中的value属性可以传入三种类型的值,分别是:直接类对象、ImportSelector和ImportBeanDefinitionRegistrar。

直接传入类对象就表示注册这些Bean;

传入ImportSelector的实现类,需要实现其中的selectImports()方法,返回的字符串数组表示要注册进容器中的Bean。例如:

public String[] selectImports(AnnotationMetadata importingClassMetadata) {
	//方法不要返回null值
	return new String[]{"com.gaishiHero.bean.Blue","com.gaishiHero.bean.Yellow"};
}

传入ImportBeanDefinitionRegistrar接口的实现类,需要实现其中的registerBeanDefinitions()方法,该方法第二个参数为BeanDefinitionRegistry,可以在该实现的方法中调用BeanDefinitionRegistry的registerBeanDefinition()方法,传入名称和BeanDefinition,就会将它们放入private final Map beanDefinitionMap = new ConcurrentHashMap<>(64);中,就算注册完成。

public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
	boolean definition = registry.containsBeanDefinition("com.gaishiHero.bean.Yellow");
	boolean definition2 = registry.containsBeanDefinition("com.gaishiHero.bean.Blue");
	if(definition && definition2){
		//定义一个BeanDefinition
		RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class);
		//注册一个Bean,指定bean名
		registry.registerBeanDefinition("rainBow", beanDefinition);
	}
}

使用FactoryBean(工厂Bean)

外形与@Bean注解类似,也是通过在配置类中写方法。不过不同点在于方法的返回值是FactoryBean的实例,此时,注册进容器中的Bean不是这个FactoryBean的实例,而是其中实现的方法getObject()的返回值。

补充说明:FactoryBean接口有三个方法需要被实现:getObject()、getObjectType()和isSingleton()。getObject()返回真实注册进IOC容器中的Bean,getObjectType()返回FactoryBean创造对象的类型,isSingleton()返回是否是单例方式,如果是单例方式,只会调用getObject()方法一次,如果不是单例,则会多次调用getObject()方法。

当然,如果我们真的需要注册进容器中的Bean就是FactoryBean的实例,则需要在获取Bean的时候给id前面加一个&,例如&colorFactoryBean

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
//bean1是getObject()方法的返回值,bean2是colorFactoryBean对象本身
Object bean1 = applicationContext.getBean("colorFactoryBean");
Object bean2 = applicationContext.getBean("&colorFactoryBean");

你可能感兴趣的:(Java,框架)