如何给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.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
appConfig3
com.sff.app.bean.Color
person
- 导入多个的方式
@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<Color> {
@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.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
appConfig3
com.sff.app.bean.Person
com.sff.app.bean.Red
colorFactoryBean
person
yellow
获取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
接口;