zoukankan      html  css  js  c++  java
  • 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容器中

  • 相关阅读:
    channel分析
    Nginx|基础
    item2
    搜索引擎技巧
    计算机网络|概述
    操作系统|进程
    分布式事务一致性
    画图工具StartUML
    内存分配
    MPG分析
  • 原文地址:https://www.cnblogs.com/AshOfTime/p/10757841.html
Copyright © 2011-2022 走看看