spring注解驱动--组件注册

  • 为容器中注册Bean

  • @Configuration代表该类是一个配置类,配置类起到的作用和xml配置文件一样
  • @Bean代表该方法的返回对象作为Bean加入IOC容器,默认Bean的id是方法的名称。可以在@Bean注解里更改value的值来更改名称
@Configuration
public class mainConfig {

    @Bean("person")
    public Person person01(){
        Person person = new Person();
        person.setId(1);
        person.setName("aa");

        return person;
    }
}

 

包扫描

  • ComponentScan配置扫描哪些包,用法和xml配置文件中的包扫描相同,包含可配置的excludeFilter和includeFilter选项。

  • excludeFilters是一个Filter类型的数组,所以这里用大括号。每一个Filter元素包含过滤条件的类型以及具体的过滤条件。如下面的Filter类型为注解,过滤条件为Controller。
@Configuration
@ComponentScan(value = "comtroller",excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Controller.class)})
public class mainConfig {

    @Bean("person")
    public Person person01(){
        Person person = new Person();
        person.setId(1);
        person.setName("aa");

        return person;
    }
}
  • includeFilters,配置只扫描哪些类型,多用于SpringMVC容器中只扫描controller注解,用法同XML配置,需要禁用默认过滤规则
@Configuration
@ComponentScan(value = "comtroller",includeFilters = {@ComponentScan.Filter(type=FilterType.ANNOTATION,classes=Controller.class)},useDefaultFilters = false)
public class mainConfig {

    @Bean("person")
    public Person person01(){
        Person person = new Person();
        person.setId(1);
        person.setName("aa");

        return person;
    }
}

 

其余常用包扫描的过滤方式

类名

  只添加或者只过滤某个具体的类

@ComponentScan(value = "comtroller",excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = BookController.class)})

自定义规则

 

如何查看包扫描是否生效

  查看包扫描是否生效就是查看Spring容器里是否有想要的Bean。

  方法一:打印出Spring容器中所有Bean。简单粗暴。

public class test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(mainConfig.class);
        String[] names = context.getBeanDefinitionNames();
        for (String name:
             names) {
            System.out.println(name);

        }
    }
}

  方法二:借助idea。每新配置一个Spring容器,无论是通过xml还是配置类方式,最好都配置idea的spring管理插件,这样可以不必运行测试类也可查看容器里的Bean

  而且在配置生效的情况下@Component注解旁边会多一个符号,点击该符号可以跳转到扫描的包。

 

改变默认单例

  Spring中的Bean默认是单例,且在容器加载的时候就被初始化。使用@Scope改变为多实例,对应的Bean在每次getBean的时候都会初始化一次,所以Bean在容器启动的时候不会初始化。背后的逻辑是单例模式是Spring容器维护了一个缓存HashMap,而多实例下并没有这个缓存。既然没有缓存那么在多实例情况下就无法存储初始化之后的Bean。

    @Bean("person")
    @Scope("prototype")
    public Person person01(){
        Person person = new Person();
        person.setId(1);
        person.setName("aa");

        return person;
    

懒加载

  针对单实例情况下容器创建时Bean就会被创建,使用@Lazy可以实现对单实例Bean在getBean的时候才加载。

按照条件注册Bean

  默认情况下被标注了@Configuration的类下所有标注@Bean的方法返回对象都会被加入Spring容器中,使用@Conditional注解可以自定义规则来只把某些Bean加入Spring容器中。

   实现Condition接口中的matches方法。conditionContext包含了一个Bean所有的信息

  • beanFactory,创建该Bean的工程
  • classLoader,该Bean的类加载器
  • enviroment,该Bean所处的环境,主要指的是OS的环境
  • register,该Bean所处的容器

  下面的代码实现两个功能:1、打印该Bean所处容器内所有的Bean 2、判断该Bean所处OS的类型,如果是Win就返回true即把Bean注入到容器中

public class WinCondition implements Condition {


    /**
     *
     * @param conditionContext 环境上下文
     * @param annotatedTypeMetadata 注释信息
     * @return
     */
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
        ClassLoader classLoader = conditionContext.getClassLoader();
        Environment environment = conditionContext.getEnvironment();

        //获得容器对象,进而判断容器中Bean的注册情况
        BeanDefinitionRegistry registry = conditionContext.getRegistry();
        String[] names = registry.getBeanDefinitionNames();

        System.out.println("====");
        for (String name :
                names) {
            System.out.println(name);
        }

        String osName = environment.getProperty("os.name");
        if (osName.contains("Win")){
            return true;
        }

        return false;
    }
}

   最后要把注解标注在方法或者配置类上。因为我的系统不是Win系统所以容器里没有zhangsan这个Bean。

 @Conditional({WinCondition.class})
    @Bean("zhangsan")
    public Person person_01(){
        return new Person("zhangsan",12);
    }

Import 

  在配置类上方标注@Import注解并声明要导入的类,会自动加到Spring中。

@Import({otherPojo.class, otherPojo2.class})
public class mainConfig {

ImportSelector

  使用上和Import类似,通过实现ImportSelector接口可以按照条件批量注册Bean,其中return的String数组中的Bean会被注册到Spring中。

public class importSelect implements ImportSelector {

    /**
     * @param annotationMetadata 当前标注Import类的全部注解信息,不仅仅是Import
     * @return 要导入容器的类的全类名
     */
    public String[] selectImports(AnnotationMetadata annotationMetadata) {

        return new String[]{"pojo.otherPojo2"};
    }
}
@Import(importSelect.class)
public class mainConfig

  Import注解是标注着配置类上的,ImportSelector中的AnnotationMetadata包含配置类所有注解的信息,通过打断点可以看到如下的结果。

FactoryBean

  实现FactoryBean接口重写getObject方法,并用@Bean方式加入Configuration中,则getObject返回的对象会加入Spring容器中

猜你喜欢

转载自www.cnblogs.com/AshOfTime/p/10757841.html