• Spring笔记(1)


    1. @Bean:类注入容器

      1. xml方式:
        <bean id="person" class="com.hrh.bean.Person">
            <property name="name" value="张三"></property>
            <property name="age" value="20"></property>
        </bean>
        public static void main(String[] args) {
            ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
            Person person = (Person) context.getBean("person");
            System.out.println(person);
        }
      2. @Bean+@Configuration方式:
        @Configuration//配置类==配置文件
        public class BeanConfig {
            @Bean
            public Person person(){
                return new Person("张三",20);
            }
        }
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class);
        Person person = (Person)context.getBean("person"); 
    2. @ComponentScan:扫描类注入容器

      1. xml方式:
        <!-- component-scan包扫描,只要标注了@Controller、@Service、@Repository、@Component的类会注入容器中
                 use-default-filters=false禁用默认过滤规则,使用自定义过滤规则
            -->
            <context:component-scan base-package="com.hrh" use-default-filters="false"/>
      2. @ComponentScan方式:JDK1.8的ComponentScan是Repeatable的,即可以在类上定义多个@ComponentScan
        @Configuration//配置类==配置文件
        /**
         * value:指定要扫描的包
         * includeFilters:指定扫描时只需要包含哪些组件,需要使用useDefaultFilters = false使规则生效
         * excludeFilters:指定扫描时按照什么规则排除哪些组件
         */
        @ComponentScan(value = "com.hrh",includeFilters = {
                @Filter(type = FilterType.ANNOTATION,
                classes = {Controller.class})
        },useDefaultFilters = false)
        public class BeanConfig {
            @Bean
            public Person person(){
                return new Person("张三",20);
            }
        }
        //====结果====
        org.springframework.context.annotation.internalConfigurationAnnotationProcessor
        org.springframework.context.annotation.internalAutowiredAnnotationProcessor
        org.springframework.context.annotation.internalCommonAnnotationProcessor
        org.springframework.context.event.internalEventListenerProcessor
        org.springframework.context.event.internalEventListenerFactory
        beanConfig
        userController
        person
      3. @ComponentScans:如果不是JDK1.8,可以使用该注解定义多个@ComponentScan
        @ComponentScans({
                @ComponentScan(value = "com.hrh",includeFilters = {
                        @ComponentScan.Filter(type = FilterType.ANNOTATION,
                                classes = {Controller.class})
                },useDefaultFilters = false)
        })
        public class BeanConfig {
            @Bean
            public Person person(){
                return new Person("张三",20);
            }
        }
      4. @Filter:过滤规则
        @Configuration//配置类==配置文件
        /**
         * FilterType.ANNOTATION:根据注解扫描指定的类
         * FilterType.ASSIGNABLE_TYPE:按照给定的类型,如果是接口类型,其实现类和子类注入容器;如果是类,本类和子类注入容器
         * FilterType.ASPECTJ:使用ASPECTJ表达式
         * FilterType.REGEX:使用正则表达式
         * FilterType.CUSTOM:使用自定义规则,自定义实现TypeFilter接口,重写match方法
         */
        @ComponentScan(value = "com.hrh", includeFilters = {
        //        @ComponentScan.Filter(type = FilterType.ANNOTATION,
        //                classes = {IUserService.class}),
        //        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,
        //        classes = {IUserService.class}),
                @ComponentScan.Filter(type = FilterType.CUSTOM,classes ={MyTypeFilter.class} )
        }, useDefaultFilters = false)
        public class BeanConfig {
            @Bean
            public Person person() {
                return new Person("张三", 20);
            }
        }
        
        public class MyTypeFilter implements TypeFilter {
            /**
             *
             * @param metadataReader 读取到的当前正在扫描的类的信息
             * @param metadataReaderFactory 可以获取到其他任何类的信息
             * @return ture则将类加入容器
             * @throws IOException
             */
            public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
                //获取当前类注解的信息
                AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
                //获取当前类资源(类路径)
                Resource resource = metadataReader.getResource();
                //获取当前正在扫描的类的类信息
                ClassMetadata classMetadata = metadataReader.getClassMetadata();
                String className = classMetadata.getClassName();
                System.out.println("className:"+className);
                if(className.contains("Controller")){
                    return true;
                }
                return false;
            }
        }
        //====结果====
        className:com.hrh.bean.Person
        className:com.hrh.config.MyTypeFilter
        className:com.hrh.controller.UserController
        className:com.hrh.dao.UserDao
        className:com.hrh.service.IUserService
        className:com.hrh.service.SubUserService
        className:com.hrh.service.UserService
        org.springframework.context.annotation.internalConfigurationAnnotationProcessor
        org.springframework.context.annotation.internalAutowiredAnnotationProcessor
        org.springframework.context.annotation.internalCommonAnnotationProcessor
        org.springframework.context.event.internalEventListenerProcessor
        org.springframework.context.event.internalEventListenerFactory
        beanConfig
        userController
        person
    3. @Scope:作用域

      @Configuration
      @ComponentScan(value = "com.hrh")
      public class BeanConfig {
          /**
           * ConfigurableBeanFactory#SCOPE_PROTOTYPE:prototype
           * ConfigurableBeanFactory#SCOPE_SINGLETON:singleton
           * org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST:request
           * org.springframework.web.context.WebApplicationContext#SCOPE_SESSION:session
           * prototype:多实例(原型),只有在获取的时候才会注入容器,每次获取都会进行创建对象注入不同的实例,每次获取的对象都不同
           * singleton:单实例(默认值),ioc容器启动会调用该方法创建对象注入容器,每次获取直接中容器中拿
           * request:同一次请求创建一个实例
           * session:同一个session创建一个实例
           */
      
          @Scope(value = "prototype")
          @Bean
          public Person person() {
              System.out.println("注入容器。。。。。");
              return new Person("张三", 20);
          }
      • @Lazy:懒加载,项目启动时不创建对象注入容器,只在第一次调用时才创建对象并初始化
            @Lazy
            @Bean
            public Person person() {
                System.out.println("注入容器。。。。。");
                return new Person("张三", 20);
            }
    4. @Conditional:按照条件注入容器,实现Condition的matches()

      @Configuration
      @ComponentScan(value = "com.hrh")
      public class BeanConfig {
          @Conditional(WindowsConfig.class)
          @Bean(value = "Bill")
          public Person person1() {
              System.out.println("创建Windows。。。。。");
              return new Person("Bill", 20);
          }
          @Conditional(LinuxConfig.class)
          @Bean(value = "Linux")
          public Person person2() {
              System.out.println("创建Linux。。。。。");
              return new Person("Linux", 20);
          }
      }
      public class WindowsConfig implements Condition {
          /**
           *
           * @param context 判断条件能使用的上下文
           * @param metadata 注释信息
           * @return
           */
          public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
              //获取ioc使用的beanFactory
              ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
              //获取类加载器
              ClassLoader classLoader = beanFactory.getBeanClassLoader();
              Environment environment = context.getEnvironment();
              String property = environment.getProperty("os.name");
              if("Windows 10".equals(property)){
                  return true;//当前系统环境是windows 10,将条件下的bean注入容器
              }
              return false;
          }
      }
      public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
              //获取ioc使用的beanFactory
              ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
              //获取类加载器
              ClassLoader classLoader = beanFactory.getBeanClassLoader();
              Environment environment = context.getEnvironment();
              String property = environment.getProperty("os.name");
              if("Linux".equals(property)){
                  return true;
              }
              return false;
          }
    5.  @Import:快速导入组件进容器

      public class Color {
      }
      @Configuration
      @ComponentScan(value = "com.hrh")
      @Import(Color.class)
      //@Import({Color.class,Person.class})导入多个
      public class BeanConfig {}
      public static void main(String[] args) {
          AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class);
          String[] beanDefinitionNames = context.getBeanDefinitionNames();
          for(String beanName:beanDefinitionNames){
              System.out.println(beanName);
          }
      }
      1. ImportSelector:实现该接口,重写selectImports()

        public class MyImportSelector implements ImportSelector {
            /**
             *
             * @param importingClassMetadata 当前标注@Import的类的全部注解信息,比如该类还标注了@Configuration也会被获取到
             * @return 返回的组件全类名加入到容器中
             */
            public String[] selectImports(AnnotationMetadata importingClassMetadata) {
                return new String[]{"com.hrh.bean.Color","com.hrh.bean.Person"};
            }
        }
        
        @Configuration
        @ComponentScan(value = "com.hrh")
        @Import({MyImportSelector.class})
        public class BeanConfig {}
      2. ImportBeanDefinitionRegistrar:实现ImportBeanDefinitionRegistrar,重写registerBeanDefinitions()

        @Configuration
        @Import({Color.class,MyImportBeanDefinitionRegistrar.class})
        public class BeanConfig {}
        public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
            /**
             *
             * @param importingClassMetadata 当前类的注解信息
             * @param registry BeanDefinition注册类,把所有需要添加到容器中的bean,调用BeanDefinitionRegistryregisterBeanDefinition注册进来
             */
            @Override
            public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
                boolean color = registry.containsBeanDefinition("com.hrh.bean.Color");
                //容器中有Color类才将Person类进行注入
                if(color) {
                    RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Person.class);
                    registry.registerBeanDefinition("person",rootBeanDefinition);
                }
        
            }
        } 
    6. FactoryBean

      public class MyFactoryBean implements FactoryBean<Color> {
          //返回一个对象,并且该对象会注入容器
          @Override
          public Color getObject() throws Exception {
      
              return new Color();
          }
      
          @Override
          public Class<?> getObjectType() {
              return Color.class;
          }
      
          @Override
          public boolean isSingleton() {
              return true;
          }
      }
      @Configuration
      public class BeanConfig {
          /**
           * 1.默认获取的是MyFactoryBean调用getObject创建的对象
           * 2.要获取MyFactoryBean本身,需要给id前加&,比如&myBeanFactory
           */
          @Bean
          public MyFactoryBean myBeanFactory(){
              return new MyFactoryBean();
          }
      }
      AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class);
      Object bean1=context.getBean("myBeanFactory");
      System.out.println(bean1.getClass());
      Object bean2=context.getBean("&myBeanFactory");
      System.out.println(bean2.getClass());
  • 相关阅读:
    获取路径的方式
    读取XML文件(XmlNode和XmlElement区别)
    jQuery 选择器大全
    JS中Null与Undefined的区别
    浅谈JS中的!=、== 、!==、===的用法和区别
    sql面试 查找每个班级的前5名学生(取分类数据的前几条数据)
    C#动态方法调用
    C# 匿名对象(匿名类型)、var、动态类型 dynamic——实用之:过滤类属性、字段实用dynamic
    前言2
    2019-1-17 前言 C#高级编程(第11版)
  • 原文地址:https://www.cnblogs.com/huangrenhui/p/12934452.html
Copyright © 2020-2023  润新知