Spring注解开发3--@Import , FacotryBean 注册bean

目录

一、@Import 手动注入bean

1.@Imoprt   bean直接传入IOC

2. @Import ImportSelector 接口

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

配置类:

扫描二维码关注公众号,回复: 3308828 查看本文章
@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 = "&";
...
}

猜你喜欢

转载自blog.csdn.net/weixin_40792878/article/details/82809709