如何给spring容器注入bean
通过前几篇笔记,总结出有如下的已知方式:
- 包扫描(
@ComponentScan
)+ 组件使用注解类(@Controller
、@Service
、@Repository
和@Component
); - 使用
@Bean
注解;
这篇笔记将记录给容器注入bean的新方式
@Import注解,快速给容器注入Bean
- 导入单个
配置我们的配置类,假如现在我们要注入一个Color对象,如何使用@Import
注解呢?如下代码所示:
@Configuration@Import(Color.class)public class AppConfig3 { /*给容器中注册一个bean,类型是方法返回值,id就是方法名称*/ @Bean public Person person() { return new Person("Kate", 12); }}
单元测试类:
public void testImport() { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig3.class); String[] names = ctx.getBeanDefinitionNames(); for (String name : names) { System.out.println(name); } }
运行结果:注入了Color对象
org.springframework.context.annotation.internalConfigurationAnnotationProcessororg.springframework.context.annotation.internalAutowiredAnnotationProcessororg.springframework.context.annotation.internalRequiredAnnotationProcessororg.springframework.context.annotation.internalCommonAnnotationProcessororg.springframework.context.event.internalEventListenerProcessororg.springframework.context.event.internalEventListenerFactoryappConfig3com.sff.app.bean.Colorperson
- 导入多个的方式
@Import({Color.class,Person.class})
@Import
注解时,容器就会自动注册这个类,bean的id默认是全类名; 使用ImportSelector
接口
ImprotSelector
接口定义如下
package org.springframework.context.annotation;import org.springframework.core.type.AnnotationMetadata;public interface ImportSelector { String[] selectImports(AnnotationMetadata importingClassMetadata);}
那么如何使用该接口来给容器注册bean呢?当然是要实现该接口了。假如现在要给容器注册Red
对象,则进行如下操作:
public class HelloImportSelector implements ImportSelector { /** * @param importingClassMetadata 标注@Import注解的类的所有注解信息 * @return 注册到容器的类的全类名 */ @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { return new String[]{"com.sff.app.bean.Red"}; }}
修改配置类即可:
@Configuration@Import({Color.class,Person.class, HelloImportSelector.class})public class AppConfig3 { /*给容器中注册一个bean,类型是方法返回值,id就是方法名称*/ @Bean public Person person() { return new Person("Kate", 12); }}
使用ImportBeanDefinitionRegistrar
接口
该接口的内容如下
package org.springframework.context.annotation;import org.springframework.beans.factory.support.BeanDefinitionRegistry;import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;import org.springframework.core.type.AnnotationMetadata;public interface ImportBeanDefinitionRegistrar { public void registerBeanDefinitions( AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);}
那么现在想给容器注入一个Yellow
类对象,操作过程如下
ImportBeanDefinitionRegistrar
接口 public class HelloBeanRegistrar implements ImportBeanDefinitionRegistrar{ @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { /*判断容器中是否存在 Red 对象*/ boolean red = registry.containsBeanDefinition("com.sff.app.bean.Red"); if(red){ /*定义一个注册对象 Yellow,这里可以知道Yellow的相关信息*/ RootBeanDefinition beanDefinition = new RootBeanDefinition(Yellow.class); /*注册一个bean*/ registry.registerBeanDefinition("yellow",beanDefinition); } }
修改配置类
@Configuration@Import({Color.class,Person.class, HelloImportSelector.class, HelloBeanRegistrar.class})public class AppConfig3 { /*给容器中注册一个bean,类型是方法返回值,id就是方法名称*/ @Bean public Person person() { return new Person("Kate", 12); }}
使用FactoryBean
还是以给容器注入Color
对象进行说明,实现FactoryBean
接口
public class ColorFactoryBean implements FactoryBean{ @Nullable @Override public Color getObject() throws Exception { return new Color(); } @Nullable @Override public Class getObjectType() { return Color.class; } /*指定是否单例*/ @Override public boolean isSingleton() { return true; }}
配置类中配置ColorFactoryBean
对象
@Configuration@Import({Person.class, HelloImportSelector.class, HelloBeanRegistrar.class})public class AppConfig3 { @Bean public ColorFactoryBean colorFactoryBean() { return new ColorFactoryBean(); }}
单元测试
public void testImport() { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig3.class); String[] names = ctx.getBeanDefinitionNames(); for (String name : names) { System.out.println(name); } Object colorFactoryBean = ctx.getBean("colorFactoryBean"); System.out.println("获取colorFactoryBean的类型:"+colorFactoryBean.getClass()); }
运行结果如下:
org.springframework.context.annotation.internalConfigurationAnnotationProcessororg.springframework.context.annotation.internalAutowiredAnnotationProcessororg.springframework.context.annotation.internalRequiredAnnotationProcessororg.springframework.context.annotation.internalCommonAnnotationProcessororg.springframework.context.event.internalEventListenerProcessororg.springframework.context.event.internalEventListenerFactoryappConfig3com.sff.app.bean.Personcom.sff.app.bean.RedcolorFactoryBeanpersonyellow获取colorFactoryBean的类型:class com.sff.app.bean.Color
从运行结果发现,在配置类中配置ColorFactoryBean
注入到容器中并不是它本身,而是Color
对象,那如果要获取ColorFactoryBean
本身,使用
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig3.class);Object colorFactoryBean = ctx.getBean("&colorFactoryBean");
就可以了。
总结
如何给容器中注册Bean?
- 包扫描(
@ComponentScan
)+ 组件使用注解类(@Controller
、@Service
、@Repository
和@Component
); - 使用
@Bean
注解; -
使用
@Import注解
注解;-
@Import
快速注册 - 实现
ImportSelector
接口 - 实现
ImportBeanDefinitionRegistrar
接口
-
- 使用
FactoryBean
接口;