Spring注解详解之组件注册(@Import,FactoryBean)
@Import
给容器中导入组件的方式大致有三种:
1.包扫描+注解(@Controller,@Service,@Repository,@Component),这适用于自己定义bean
2.通过@Bean注解,这适用于导入第三方包里的bean
3.通过@Import,快速的向容器中注入bean
3.1:@Import(Class):容器中就会自动注册该bean,ID默认全类型
3.2:ImportSelector:返回需要导入的组件的全类名数组
3.3:ImportBeanDefinitionRegistrar:自定义bean定义注册器,手动注册bean
4.使用spring提供的FactoryBean(工厂bean)注入
4.1:通过工厂创建的对象,默认获取的是泛型指定对象,也就是getObject方法获取的对象
4.2:若要获取工厂bean本身对象,需要在bean的ID前加&标识来获取
3.1示例:
//创建一个测试类User
public class User {
}
//配置类
@Configuration
@Import(User.class)
public class MyConfig3 {
}
//测试方法
@Test
public void testImport(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig3.class);
String[] names = applicationContext.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
}
//输出结果,可见已经注入了user,ID默认是类的全路径名
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
myConfig3
com.ming.bean.User
3.2示例
ImportSelector:返回需要导入的组件的全类名数组
//自定义导入选择器
public class MyImportSelector implements ImportSelector {
/*
返回值:需要导入的类的全路径名数组
AnnotationMetadata:标准@Import注解的类的注解信息
*/
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.ming.bean.Student","com.ming.bean.Person"};
}
}
//配置类
@Configuration
@Import({User.class, MyImportSelector.class})
public class MyConfig3 {
}
//测试方法
@Test
public void testImport(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig3.class);
String[] names = applicationContext.getBeanDefinitionNames();
for (String name : names) {
System.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
myConfig3
com.ming.bean.User
com.ming.bean.Student
com.ming.bean.Person
3.3示例
//自定义bean导入注册器
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/*
AnnotationMetadata:当前注解@Import类的注解信息
BeanDefinitionRegistry:Bean的注册类,可以调用registerBeanDefinition手工注册bean,
*/
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean b = registry.containsBeanDefinition("com.ming.bean.Student");
//判断容器中有student则注入teacher
if (b) {
BeanDefinition beanDefinition = new RootBeanDefinition(Teacher.class);
registry.registerBeanDefinition("teacher",beanDefinition);
}
}
}
//配置类
@Configuration
@Import({User.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MyConfig3 {
}
//测试方法
@Test
public void testImport(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig3.class);
String[] names = applicationContext.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
}
//输出结果,存在student并且注入了teacher
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
myConfig3
com.ming.bean.User
com.ming.bean.Student
com.ming.bean.Person
teacher
FactoryBean
使用spring提供的FactoryBean(工厂bean)注入
- 通过工厂创建的对象,默认获取的是泛型指定对象,也就是getObject方法获取的对象
- 若要获取工厂bean本身对象,需要在bean的ID前加&标识来获取
示例
//自定义工厂bean
public class UserFactoryBean implements FactoryBean<User> {
@Override
public User getObject() throws Exception {
return new User();
}
@Override
public Class<?> getObjectType() {
return User.class;
}
//默认是true,是单例的,如果重写false,则是多例的
public boolean isSingleton() {
return true;
}
}
//配置类
@Configuration
@Import({User.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MyConfig3 {
//注入自定义的工厂bean
@Bean
public UserFactoryBean userFactoryBean(){
return new UserFactoryBean();
}
}
//测试方法
@Test
public void testImport(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig3.class);
String[] names = applicationContext.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
Object factoryBean1 = applicationContext.getBean("userFactoryBean");
Object factoryBean2 = applicationContext.getBean("userFactoryBean");
System.out.println("userFactoryBean类型:"+factoryBean1.getClass());
System.out.println(factoryBean1 == factoryBean2);
Object factoryBean3 = applicationContext.getBean("&userFactoryBean");
System.out.println(factoryBean3.getClass());
}
//输出结果,发现通过ID:userFactoryBean获取到的对象是getObject方法返回的对象,要获取工厂bean本身,需要在ID前加&
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
myConfig3
com.ming.bean.User
com.ming.bean.Student
com.ming.bean.Person
userFactoryBean
teacher
userFactoryBean类型:class com.ming.bean.User
true
class com.ming.condition.UserFactoryBean
在spring的源码,BeanFactroy源码中,有定义这个FACTORY_BEAN_PREFIX前缀,通过上面的描述信息,可以看出通过加该前缀可以获取工厂bean本身