我是靠谱客的博主 眯眯眼长颈鹿,最近开发中收集的这篇文章主要介绍Spring注解(一):组件注册,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

  1. @Configuration
  2. @Bean
    
    //@Bean//给容器注入一个bean,类型为返回值的类型,id默认方法名就是id
    @Bean("person")//指定id为person
    public Person person(){
    return new Person("李四",12);
    }
    <!-- 该注解对应的xml实现方式 -->
    <bean id="persion" class="indi.com.bean.Person">
    <property name="name" value="张三"></property>
    <property name="age" value="18"></property>
    </bean>
    
    1. 默认是单例的
    2. 设置为多实例:@Scope
  3. @Scope
    
    //@Bean//给容器注入一个bean,类型为返回值的类型,id默认方法名就是id
    @Scop("prototype")
    @Bean("person")//指定id为person
    public Person person(){
    return new Person("李四",12);
    }
    <!-- 该注解对应的xml实现方式 -->
    <bean id="persion" class="indi.com.bean.Person" scope="prototype">
    <property name="name" value="张三"></property>
    <property name="age" value="18"></property>
    </bean>
    
    1. singleton:单实例(默认):IOC容器启动器会调用方法创建对象放到IOC容器中,以后每次使用时都直接从容器(map.get())中拿。
    2. prototype:多实例:IOC容器启动器时并不会调用方法创建对象放到容器中,每次获取时才会调用方法创建对象,每次获取都会调用方法创建对象。
    3. request:同一次请求创建一个实例
    4. session:同一个session创建一个实例
  4. @Lazy:针对单实例bean
    1. 单实例bean:默认容器加载时创建对象
    2. 使用@Lazy:容器加载时不创建对象,第一次使用(获取)bean对象时创建对象并初始化
      
      @Lazy
      @Bean("person")//指定id为person
      public Person person(){
      return new Person("李四",12);
      }
  5. @Conditional:
    1. 按照一定的条件判断,满足条件时给容器注册bean
    2. 可以放在方法上,也可以放在类上(类中组件统一设置)
    3. 使用方法:
      1. 写Condition的实现类
        package indi.com.config;
        import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
        import org.springframework.beans.factory.support.BeanDefinitionRegistry;
        import org.springframework.context.annotation.Condition;
        import org.springframework.context.annotation.ConditionContext;
        import org.springframework.core.env.Environment;
        import org.springframework.core.type.AnnotatedTypeMetadata;
        public class LinuxCondition implements Condition {
        /**
        *
        * @param conditionContext:判断条件使用的上下文(环境)
        * @param annotatedTypeMetadata:注释信息
        * @return
        */
        public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        //获取IOC使用的beanFactory
        ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
        //获取类加载器
        ClassLoader classLoader = conditionContext.getClassLoader();
        //获取当前环境
        Environment environment = conditionContext.getEnvironment();
        //获取bean定义的注册类
        BeanDefinitionRegistry registry = conditionContext.getRegistry();
        //容器中bean的注册情况
        boolean person = registry.containsBeanDefinition("person");
        //获取系统信息
        String property = environment.getProperty("os.name");
        if(property.contains("linux")){
        return true;
        }
        return false;
        }
        }
        
      2. 注解

        package indi.com.config;
        import indi.com.bean.Person;
        import org.springframework.context.annotation.*;
        import org.springframework.stereotype.Controller;
        import org.springframework.stereotype.Service;
        @Configuration
        @ComponentScan(value="indi.com")
        public class BeanConfig {
        @Conditional({LinuxCondition.class})
        @Bean("linux")
        public Person linux(){
        return new Person("linux",55);
        }
        }
        
  6. @ComponentScan
    1. value:指定要扫描的包
      @ComponentScan(value="indi.com")
      <!-- 该注解对应的xml实现方式 -->
      <context:component-scan base-package="indi.com"></context:component-scan>
    2. excludeFilters = Filter[]:扫描时排除指定的组件
      @ComponentScan(value="indi.com",excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class, Service.class})})
    3. includeFilters=Filter[]:扫描时只需要包含指定的组件
      1. 需要禁用默认的扫描规则:userDefaultFilters=false;
        @ComponentScan(value="indi.com",includeFilters = {@ComponentScan.Filter(type=FilterType.ANNOTATION,classes ={Controller.class})},useDefaultFilters = false)})
        <!-- 该注解对应的xml实现方式 -->
        <context:component-scan base-package="indi.com" use-default-filters="false"></context:component-scan>
        
    4. @Filter
      1. type
        1. FilterType.ANNOTATION:按照注解
          type=FilterType.ANNOTATION
        2. FilterType.ASSIGNABLE_TYPE:按照给定的类型
          type=FilterType.ASSIGNABLE_TYPE
        3. FilterType.ASPECTJ:按照ASPECTJ表达式
        4. FilterType.REGEX:按照正则
        5. FilterType.CUSTOM:自定义规则
          1. 写一个TypeFilter的实现类:MyTypeFilter
            package indi.com.config;
            import org.springframework.core.io.Resource;
            import org.springframework.core.type.AnnotationMetadata;
            import org.springframework.core.type.ClassMetadata;
            import org.springframework.core.type.classreading.MetadataReader;
            import org.springframework.core.type.classreading.MetadataReaderFactory;
            import org.springframework.core.type.filter.TypeFilter;
            import java.io.IOException;
            public class MyTypeFilter implements TypeFilter {
            /**
            *
            * @param metadataReader:读取当前正在扫描的类的信息
            * @param metadataReaderFactory:可以获取其他任何类的信息
            * @return
            * @throws IOException
            */
            public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
            //获取当前类注解的信息
            AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
            //获取当前正在扫描类的类信息
            ClassMetadata classMetadata = metadataReader.getClassMetadata();
            //获取当前类的资源(类路径)
            Resource resource = metadataReader.getResource();
            //类名
            String className = classMetadata.getClassName();
            System.out.println(className);
            if(className.contains("er")){
            return true;
            }
            return false;
            }
            }
            
          2. 配置
            
            @ComponentScan(value="indi.com",@Filter(type=FilterType.CUSTOM,class={MyTypeFilter}))
          3. 注意:根据MyTypeFilter的规则可知,在indi.com包下,所有类名中包含"er"的类(无论该类上是否有注解)都能扫描到
  7. @ComponentScans
  8. @Import
    1. 方式一:
      //id默认是组件的全类名
      @Import(类名.class)或者@Import({类名1.class,类名2.class})
    2. 方式二:
      1. 写一个类实现ImportSelector
        package indi.com.config;
        import org.springframework.context.annotation.ImportSelector;
        import org.springframework.core.type.AnnotationMetadata;
        //自定义逻辑返回需要导入的组件
        public class MyImportSelector implements ImportSelector {
        /**
        *
        * @param annotationMetadata:当前标注@Import注解的类的所有注解信息
        * @return:导入到容器中的组件全类名
        */
        public String[] selectImports(AnnotationMetadata annotationMetadata) {
        //return new String[0];//默认
        return new String[]{类1的全路径,类2的全路径};
        }
        }
        
      2. 配置
        //id默认是组件的全类名
        @Import(类名.class)或者@Import({类名1.class,类名2.class,MyImportSelector.class})
    3. 方式三:
      1. 写一个类实现ImportBeanDefinitionRegistrar
        package indi.com.config;
        import org.springframework.beans.factory.support.BeanDefinitionRegistry;
        import org.springframework.beans.factory.support.RootBeanDefinition;
        import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
        import org.springframework.context.annotation.ImportSelector;
        import org.springframework.core.type.AnnotationMetadata;
        public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
        /**
        *
        * @param annotationMetadata:当前类的注解信息
        * @param beanDefinitionRegistry:beanDefinition注册类
        *
        将所有需要添加到容器中的bean,
        *
        通过beanDefinitionRegistry.registerBeanDefinition手工注册进来
        */
        public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
        boolean test = beanDefinitionRegistry.containsBeanDefinition("类的全路径");
        if(test){
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(类.class);
        beanDefinitionRegistry.registerBeanDefinition("test",rootBeanDefinition);
        }
        }
        }
        
      2. 配置
        //id默认是组件的全类名
        @Import(类名.class)或者@Import({类名1.class,类名2.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})
  9. FactoryBean(工厂Bean)
    1. 创建Spring定义的FactoryBean,实现FactoryBean
    2. 将创建的FactoryBean加入容器中
      1. 注意:工厂Bean获取的是调用getObject创建的对象
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        Object bean = applicationContext.getBean("工具bean的注册ID");
      2. 获取工厂Bean本身:
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        Object bean = applicationContext.getBean("&工具bean的注册ID");

 

总结:给容器中注册组件

  • 包扫描+组件标注注解(@Controller、@Service、@Repository、@Component)
  • @Bean:导入第三方包里面的组件
  • @Import:快速给容器中导入一个组件
    • @Import(类名.class):容器中自动导入这个组件,id默认为全类名
    • ImportSelector:返回需要导入的组件的全类名数组
    • ImportBeanDefinitionRegistrar:手动注册bean到容器中
  • 使用Spring提供的FactoryBean
    • 默认获取的是工厂bean调用的getObject创建的对象
    • 要获取工厂bean本身,需要给id前面加一个&

最后

以上就是眯眯眼长颈鹿为你收集整理的Spring注解(一):组件注册的全部内容,希望文章能够帮你解决Spring注解(一):组件注册所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(37)

评论列表共有 0 条评论

立即
投稿
返回
顶部