目录
3. @Import ImportBeanDefinitionRegistrar
二、使用FactoryBean(工厂bean) 注册bean
@ComponentScan注解用于扫描自己写的类(@Controller,@Service,@Component,@Repository),用于加入IOC容器中
@Bean 可以把其他包或者自己写的类加到IOC容器中
@Import 也可以办到Bean类似的功能,快速导入IOC容器中,id默认是全类名
一、@Import 手动注入bean
可以传入三种参数,
- 直接传入需要加入IOC的bean的类,
- 使用Importselect ,
- 使用ImportBeanDefinitionRegistrar
1.@Imoprt bean直接传入IOC
配置类:
@Configuration
@Import(Car.class) //这里可以传入一个数组
public class MainConfig {
@Bean(value = "user01")
public User user01(){
return new User("vison01",23);
}
}
测试类:
public class TestAnotation {
public static void main(String[] args) {
AnnotationConfigApplicationContext configApplicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
String[] beanDefinitionNames = configApplicationContext.getBeanDefinitionNames();
Arrays.stream(beanDefinitionNames).forEach(bean -> System.out.println(bean));
}
}
结果显示:@import是全类名,bean就是定义的类名,配置类也会放到容器中
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
mainConfig
com.wusu.annotation.Car
user01
2. @Import ImportSelector 接口
ImportSelector 这个是一个接口,其中的方法只有一个,相当于同时传入多个Bean,可以再这个实现类做一些判断
需要返回导入组件的全类名数组如下:
2.1 实现ImportSelector这个接口,这里表示要传入House和Plane两个类
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
//annotationMetadata 表示标注@Import注解的类的注解信息
//这个方法不能反悔null,否则会抛出空指针
return new String[]{"com.wusu.annotation.House","com.wusu.annotation.Plane"};
}
}
2.2 配置类 ,获取到的bean的id同样是全类名
@Configuration
@Import({Car.class,MyImportSelector.class})
public class MainConfig {
@Bean(value = "user01")
public User user01(){
return new User("vison01",23);
}
}
3. @Import ImportBeanDefinitionRegistrar
ImportBeanDefinitionRegistrar也是一个接口,在其中直接注册bean ;这种方式可以加很多判断条件
3.1 实现接口ImportBeanDefinitionRegistrar的类
public class MyImportBeanDefinitionRegister implements ImportBeanDefinitionRegistrar {
//annotationMetadata 表示标注@Import注解的类的注解信息
//beanDefinitionRegistry :bean的注册类,所有的bean都是通过这个类来注册的
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
boolean user01 = beanDefinitionRegistry.containsBeanDefinition("user01");
boolean b = beanDefinitionRegistry.containsBeanDefinition("com.wusu.annotation.Car");
//这个类是定义bean信息的,可以加scope,lazy等信息
RootBeanDefinition beanDefinition = new RootBeanDefinition(Bicycle.class);
if (user01 && b){ //判断当上面的两个bean都被注册的情况下,才会注册下面这个bean
beanDefinitionRegistry.registerBeanDefinition("bicycle",beanDefinition);
}
}
}
3.2 配置类
@Configuration
@Import({Car.class,MyImportBeanDefinitionRegister.class})
public class MainConfig {
@Bean(value = "user01")
public User user01(){
return new User("vison01",23);
}
}
二、使用FactoryBean(工厂bean) 注册bean
1)默认获取到的是工厂bean通过getObject获取到的bean
2)要获取工厂bean本身,需要给id前加“&”。
1.先实现FactoryBean
public class MyFactoryBean implements FactoryBean<Car> {
//返回一个Car对象,这个对象会添加到IOC容器中
@Override
public Car getObject() throws Exception {
return new Car();
}
//类的信息
@Override
public Class<?> getObjectType() {
return Car.class;
}
//控制这个类是否是单例,返回true表示单例,反之是多例
@Override
public boolean isSingleton() {
return true;
}
}
2.配置类配置这个FactoryBean
@Configuration
public class MainConfig {
@Bean(value = "user01")
public User user01(){
return new User("vison01",23);
}
@Bean
public MyFactoryBean myFactoryBean(){
return new MyFactoryBean();
}
}
3.测试类
public class TestAnotation {
public static void main(String[] args) {
AnnotationConfigApplicationContext configApplicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
String[] beanDefinitionNames = configApplicationContext.getBeanDefinitionNames();
Arrays.stream(beanDefinitionNames).forEach(bean -> System.out.println(bean));
Object bean = configApplicationContext.getBean("myFactoryBean");
System.out.println(bean.getClass()); //这个结果不是myFactoryBean的信息而是com.wusu.annotation.Car
}
}
如上获取的结果始终是在Factorybean中声明的类,如果要获取当前这个FactoryBean怎么处理呢
Object bean = configApplicationContext.getBean("&myFactoryBean"); 这个id名前加一个“&”符号,那么获取的结果就是com.wusu.annotation.bean.MyFactoryBean
可以看到BeanFactory源码中定义了这个符号:
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
...
}