• spring通过注解注册bean的方式+spring生命周期


    spring容器通过注解注册bean的方式

    1. @ComponentScan + 组件标注注解 (@Component/@Service...)
      @ComponentScan(value = "com.example.demo.annotation")
      
      spring会将com.example.demo.annotation目录下标注了spring能识别的注解的类注册为bean
      @ComponentScan 还可以指定排除和包含规则
      • excludeFilters: 指定排除规则,排除哪些组件
      • includeFilters: 指定只需要包含哪些组件,需要设置 useDefaultFilters = false
      • FilterType.ANNOTATION 基于注解过滤
      • FilterType.ASSIGNABLE_TYPE : 基于给定的类型过滤
      • ...
      • FilterType.CUSTOM: 自定义规则过滤
      @ComponentScan(value = "com.example.demo.annotation",
              /*excludeFilters = {
                      @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
              },*/
              includeFilters = {
                      @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Configuration.class}),
                      @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {TestController.class}),
                      @ComponentScan.Filter(type = FilterType.CUSTOM,classes = {MyTypeFilter.class})
              },useDefaultFilters = false
      )
      
      其中CUSTOM自定义规则中的MyTypeFilter需要实现TypeFilter接口,举例如下
      public class MyTypeFilter implements TypeFilter {
          @Override
          public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
              String className = metadataReader.getClassMetadata().getClassName();
              System.out.println("------>"+className);
              if (className.contains("er")){
                  return true;
              }
              return false;
          }
      }
      
    2. @Bean (可以将第三方包中的类注册为bean)
      @Bean
      Person person() {
          return new Person("zhang");
      }
      
    3. @Import
      @Import({Color.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
      
      • 导入一个普通类,容器会自动注册这个组件,组件的id默认是类的全类名
      • 导入ImportSelector :返回需要注册的组件
      public class MyImportSelector implements ImportSelector {
          @Override
          public String[] selectImports(AnnotationMetadata annotationMetadata) {
              return new String[]{"com.example.demo.annotation.bean.Red"};
          }
      }
      
      • 导入ImportBeanDefinitionRegistrar
      public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
      
          @Override
          public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
              boolean b = registry.containsBeanDefinition("com.example.demo.annotation.bean.Color");
              boolean b1 = registry.containsBeanDefinition("com.example.demo.annotation.bean.Red");
              if (b && b1){
                  registry.registerBeanDefinition("rainBow",new RootBeanDefinition(RainBow.class));
              }
          }
      }
      
    4. 使用spring提供的 FactoryBean
      public class ColorFactoryBean implements FactoryBean<Color> {
          @Override
          public Color getObject() throws Exception {
              return new Color();
          }
      
          @Override
          public Class<?> getObjectType() {
              return Color.class;
          }
      }
      
      @Bean
      ColorFactoryBean colorFactoryBean() {
          return new ColorFactoryBean();
      }
      
      applicationContext.getBean("colorFactoryBean") 默认获取到的是FactoryBean调用getObject方法返回的对象
      要获取FactoryBean本身,需要在id前面加个& (&colorFactoryBean)

    当满足某种条件时才注册bean,使用@Conditional

    举例:在windows和linux上分别注册不同的bean

        @Conditional({WindowsConditional.class})
        @Bean("windows")
        Person person1() {
            return new Person("windows");
        }
    
        @Bean("linux")
        @Conditional({LinuxConditional.class})
        Person person2() {
            return new Person("linux");
        }
    
        public class WindowsConditional implements Condition {
            @Override
            public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
                Environment environment = conditionContext.getEnvironment();
                String property = environment.getProperty("os.name");
                return property.toLowerCase().contains("windows");
            }
        }
    
        public class LinuxConditional implements Condition {
            @Override
            public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
                Environment environment = conditionContext.getEnvironment();
                String property = environment.getProperty("os.name");
                return property.toLowerCase().contains("linux");
            }
        }
    

    bean的生命周期

    spring容器管理bean的生命周期:创建--》初始化--》销毁

    我们可以自定义初始化和销毁方法,容器在bean进行到当前生命周期时来调用我们自定义的初始化和销毁方法

    1. 创建对象:
      单实例:在容器启动时创建对象
      多实例:在每次获取bean的时候创建对象

      每个BeanPostProcessor的 postProcessBeforeInitialization 方法会在初始化之前执行

    2. 初始化: 对象创建好,调用初始化方法
      每个BeanPostProcessor的 postProcessAfterInitialization 方法会在初始化之后执行

    3. 销毁:
      单实例:容器关闭时销毁
      多实例:容器会帮助创建这个bean,但不会管理这个bean,所以容器不会调用销毁方法,可以手动调用销毁方法

    指定初始化和销毁的方法:

    1. 在 @Bean注解指定(initMethod = "",destroyMethod = "")
    2. 通过让bean实现 InitializingBean(定义初始化逻辑) 和 DisposableBean(定义销毁时逻辑)
    3. 使用JSR250: @PostConstruct (定义初始化逻辑) @PreDestroy(在容器销毁bean之前通知进行清理工作)

    bean的后置处理器 BeanPostProcessor,其有如下两个方法,在bean的初始化前后做一些处理:

    • postProcessBeforeInitialization:在初始化之前工作
    • postProcessAfterInitialization:在初始化之后工作
    @Component
    public class MyBeanPostProcessor implements BeanPostProcessor {
        private final ApplicationContext applicationContext;
    
        public MyBeanPostProcessor(ApplicationContext applicationContext) {
            this.applicationContext = applicationContext;
        }
    
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("postProcessBeforeInitialization--->"+beanName);
            return bean;
        }
    
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("postProcessAfterInitialization--->"+beanName);
            return bean;
        }
    }
    

    如果自定义组件想要使用spring容器底层的组件(ApplicationContext,BeanFactory,***),自定义组件可以实现 ***Aware,
    在创建bean的时候,相关BeanPostProcessor会调用接口规定的方法注入相关组件

    例如:

    如果自定义bean 实现了ApplicationContextAware 接口,在ApplicationContextAwareProcessor中会调用ApplicationContextAware的
    setApplicationContext方法,注入ApplicationContext组件

  • 相关阅读:
    使用selenium模拟登陆12306以及滑块验证
    网络爬虫之requests模块
    网络爬虫简介
    MongoDB基础操作
    redis集群搭建以及常见问题
    redis的主从复制
    Linux下如何安装mysql
    python 序列化模块
    python os模块和sys模块
    python 时间模块
  • 原文地址:https://www.cnblogs.com/yloved/p/15635837.html
Copyright © 2020-2023  润新知