zoukankan      html  css  js  c++  java
  • Spring五、注解编程基础组件


      Spring5开启了零配置编程时代,脱离xml完全使用注解编程,为Spring Boot奠定了开发基础。
      案例demo地址

    一、配置组件

    1. @Configuration

      声明一个类为Spring IOC容器,如果这个类方法头上注册了@Bean,就会作为Spring容器中的Bean。等价于xml配置文件。

    @Configuration
    public class MyConfig {
    
        /**
         * 1. 默认类名首字母小写
         * 2. 其次就是取方法名
         * 3. 最后优先取Bean的value
         * @return
         */
        @Bean(value = "myPerson")
        public Person getPerson() {
            System.out.println("create person by myself");
            return new Person("shen", "18");
        }
    
    }
    
      普通xml方式配置的IOC容器获取方法:
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
        Person person = (Person) applicationContext.getBean("myPerson");
      注解@Configuration方式配置的IOC容器获取方法:
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
        Person person = (Person) applicationContext.getBean("person");
    

    2. @ComponentScan、@ComponentScans

      在配置类上添加@ComponentScan注解,相当于之前的context:component-scan

    @Configuration
    //1. 简单使用ComponentScan注解扫描,扫描包下的bean使用@Service、@Controller、@Component等注解配合,可以扫描到
    //@ComponentScan(value = "com.bigshen.demo.project")
    //2. useDefaultFilters = false, 不使用Spring默认的扫描filter,
    //  自己指定扫描规则
    @ComponentScan(
            value = "com.bigshen.demo.project",
            useDefaultFilters = false,       // 使用自定义的扫描过滤规则
            includeFilters = {
    //                @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Controller.class),  // 使用注解扫描
    //                @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = MyDao.class),     // 直接指定类型扫描
                    @ComponentScan.Filter(type = FilterType.CUSTOM, value = MatchedFilter .class)},     // 直接自定义类型扫描
            excludeFilters = {
                    @ComponentScan.Filter(type = FilterType.CUSTOM, value = UnMatchedFilter.class)   // 直接自定义类型排除
            }
            )
    public class MyConfig {
    
    
    }
    
    
    
    public class MatchedFilter implements TypeFilter {
    
        /**
         *
         * @param metadataReader  类的信息
         * @param metadataReaderFactory  spring上下文
         * @return
         * @throws IOException
         */
        @Override
        public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
    
            // 当前类注解的信息
            AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
            // 当前类的信息
            ClassMetadata classMetadata = metadataReader.getClassMetadata();
            // 当前资源信息
            Resource resource = metadataReader.getResource();
    
            String clazzName = classMetadata.getClassName();
            System.out.println("--------- " + clazzName);
    
            if (clazzName.contains("er")){
                return true;
            }
            return false;
        }
    
    }
    
    
    public class UnMatchedFilter implements TypeFilter {
    
        @Override
        public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
    
            ClassMetadata classMetadata = metadataReader.getClassMetadata();
    
            String className = classMetadata.getClassName();
            if (className.contains("Controller")) {
                // 不匹配
                return true;
            }
            return false;
        }
    
    }
    

    3. @Scope

      指定类的作用域,singleton、prototype、request、session

    4. @Lazy

      Spring中Bean默认是非懒加载的,即在容器初始化时就将实例初始化,使用@Lazy注解指定该Bean为懒加载。

    5. @Conditional

      Spring4开始提供,按照一定的条件进行判断,满足条件给容器注册Bean。 自定义的条件实现'org.springframework.context.annotation.Condition'

      public class WindowCondition implements Condition {
    
        @Override
        public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
    
            ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
            Environment environment = context.getEnvironment();
            String system = environment.getProperty("os.name");
            System.out.println("System --  " + system);
            if (system.contains("Window")) {
                return true;
            }
            return false;
        }
    
    }
    
    @Configuration
    public class MyConfig {
    
        @Conditional(WindowCondition.class)
        @Bean
        public Person shen() {
            System.out.println("将shen添加到ioc容器中");
            return new Person("Shen", "18");
        }
    
        @Bean
        @Conditional(LinuxCondition.class)
        public Person liu() {
            System.out.println("将liu添加到ioc容器中");
            return new Person("liu", "18");
        }
    
        @Bean
        @Conditional(WindowCondition.class)
        public Person wang() {
            System.out.println("将wang添加到ioc容器中");
            return new Person("wang", "18");
        }
    
    }
    

    6. @Import

      导入外部资源
      @Import源码,可以指定 org.springframework.context.annotation.ImportSelector 或者 org.springframework.context.annotation.ImportBeanDefinitionRegistrar 的实现类来作为导入规则,也可以是普通的类

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Import {
    
    	/**
    	 * {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar}
    	 * or regular component classes to import.
    	 */
    	Class<?>[] value();
    
    }
    
    

      
    @Configuration
    @Import(value = {Cat.class, MyImport.class, MyRegistry.class})
    public class MyConfig {
    
        /**
         *
         * 注册Bean的几种方式
         * 1. @Bean 导入单个Bean
         * 2. @ComponentScan (默认扫描 @Controller、@Service、@Repository、@Component)
         * 3. @Import 快速导入Bean
         *      a. @Import 直接参数导入
         *      b. 实现 ImportSelector 自定义规则实现
         *      c. 实现 ImportBeanDefinitionRegistrar 直接往IOC容器中注册
         * 4. FactoryBean , 把需要注册的对象封装为FactoryBean
         *      a. FactoryBean 负责将Bean注册到Ioc的Bean
         *      b. BeanFactory Ioc容器,从中获得Bean对象
         * @return
         */
        @Bean
        public Person person() {
            return new Person("shen", "19");
        }
    
        @Bean
        public FactoryBean world() {
            return new MyFactoryBean();
        }
    
    }
    
    
    public class MyImport implements ImportSelector {
    
        @Override
        public String[] selectImports(AnnotationMetadata importingClassMetadata) {
            // 直接返回 class集合,放入IOC容器
            return new String[]{"com.bigshen.demo.project.entity.Apple", "com.bigshen.demo.project.entity.Orange"};
        }
    
    }
    
    public class MyRegistry implements ImportBeanDefinitionRegistrar {
    
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            // 包里同时声明了Apple 和 Orange ,才把Fruit放入IOC容器
    
            Boolean containsApple = registry.containsBeanDefinition("com.bigshen.demo.project.entity.Apple");
            Boolean containsOrange = registry.containsBeanDefinition("com.bigshen.demo.project.entity.Orange");
    
            if (containsApple && containsOrange) {
                BeanDefinition beanDefinition = new RootBeanDefinition(Apple.class);
                registry.registerBeanDefinition("apple", beanDefinition);
            }
    
        }
    
    }
    
    public class MyFactoryBean implements FactoryBean<World> {
    
        @Override
        public World getObject() throws Exception {
            return new World();
        }
    
        @Override
        public Class<?> getObjectType() {
            return World.class;
        }
    
        @Override
        public boolean isSingleton() {
            return true;
        }
    }
    

    7.生命周期控制 @PostConstruct、@PreDestroy、@DependsOn

      @PostConstruct 用在方法上,用于指定Bean的初始化方法
      @PreDestroy 用在方法上,用于指定销毁方法
      @DependsOn 定义Bean初始化及销毁时的顺序
    
      /**
         *  bean的生命周期 : 创建(实例化-初始化)、使用、销毁
         * 3中方式都可实现 对生命周期进行控制:
         * a、@PostConstruct、@PreDestroy
         * b、@Bean本身的 initMethod()、destroyMethod()
         * c、接口 InitializingBean#afterPropertiesSet()、DisposableBean#destroy()
         * @return
         */
    
    Bean的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:
    
    1、Bean自身的方法  :  这个包括了Bean本身调用的方法和通过配置文件中<bean>的init-method和destroy-method指定的方法
    
    2、Bean级生命周期接口方法  :  这个包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这些接口的方法
    
    3、容器级生命周期接口方法  :  这个包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。
    
    4、工厂后处理器接口方法  :  这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工厂后处理器  接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。
    

    二、赋值组件、自动装配

    1. @Componment

      泛指组件,当组件不好归类时使用

    2. @Service、@Controller、@Repository

      @Service 用于标注业务层组件
      @Controller 用于标注控制层组件
      @Repository 用于标注数据访问层、即Dao层组件

    3. @Value

      普通数据类型赋值 可结合Spring EL表达式从配置文件取值

        @Value("${child.family}")
        private String family;
    

    4. @Autowired

      默认按照类型装配,如果想按名称进行装配,可配合@Qualifier使用

    5. @Resource

      按照名称装配,如果找不到名称匹配的Bean则会按照类型装配

    6 @PropertySource

      读取配置文件

    @Configuration
    @PropertySource("classpath:values.properties")
    public class MyConfig {
    
        @Bean
        public Child child() {
            return new Child();
        }
    
    }
    

    7. @Qualifier

      如存在多个实例,配合@Autowired使用,指定根据名称装配

        @Autowired
        @Qualifier("childService")
        public HumanService humanService;
    
    

    8. @Primary

      自动装配时如果匹配到多个Bean,使用@Primary作为首选者,否则抛出异常
      如一个接口有多个实现类,这些实现类中有一个使用了@Primary注解,则在@Autowired注入时会优先使用这个实现类

    三、织入组件

    1. ApplicationContextAware

      可以通过这个上下文环境对象得到Spring容器中的Bean

    2. BeanDefinitionRegistryPostProcessor

      BeanDefinitionRegistryPostProcessor实现了BeanFactoryPostProcessor接口,是Spring框架的BeanDefinitionRegistry的后处理器,用来注册额外的BeanDefinition

    四、切面组件

    1. @EnableTransactionManagement

     启用对事物管理的支持

    2. @Transactional

     配置声明式事物信息

  • 相关阅读:
    Eclipse中jsp、js文件编辑时,卡死现象解决汇总
    环境安装备忘录 Nginx
    环境安装备忘录 Redis redis-slave-端口号.conf
    环境安装备忘录 Redis redis-common.conf
    环境安装备忘录 Redis
    Leetcode 131 Palindrome Partitioning(DFS思路)
    排序算法之快速排序(Quick Sort) -- 适用于Leetcode 75 Sort Colors
    谈STL的重要应用与实现
    二分图匹配相关问题
    理解操作系统相关知识
  • 原文地址:https://www.cnblogs.com/Qkxh320/p/spring_05.html
Copyright © 2011-2022 走看看