zoukankan      html  css  js  c++  java
  • Spring IOC容器底层常见注解使用

    一、说明

      拥抱Springboot,基于各种读取配置类的形式,了解常见IOC底层注解实用。

    二、注解详解demo

      2.1、配置定义bean 

    @Configuration
    public class MainConfig {
    
        /**
         * 注意,当 @Bean 没有指定value或者name的时候,默认的beanName为方法名。
         */
        @Bean
        public Person person2(){
            return new Person();
        }
    }

      去容器中读取bean

    public class MainTest {
    
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
            System.out.println(context.getBean(Person.class));
            System.out.println(context.getBean("person2"));
        }
    }

      2.2、配置类的@ComponentScan注解扫描

    @Configuration
    //@ComponentScan(basePackages = {"com.cfang.ioc.compantscan"})
    @ComponentScan(basePackages = {"com.cfang.ioc.compantscan"},excludeFilters = {
            @ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Controller.class}),
            @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = {UserService.class}),
            @ComponentScan.Filter(type = FilterType.CUSTOM, value = {CustomFilterType.class})
    })
    public class MainConfig {
    }

      basePackages :配置基本扫描的包路径

           excludeFilters :配置排除扫描的规则,ANNOTATION-基于注解、ASSIGNABLE_TYPE-指定类型、CUSTOM-自定义规则

    public class CustomFilterType implements TypeFilter {
        @Override
        public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
            //当前类的注解源信息
            AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
            //当前类class源信息
            ClassMetadata classMetadata = metadataReader.getClassMetadata();
            //当前类资源信息
            Resource resource = metadataReader.getResource();
            System.out.println("类的路径:"+classMetadata.getClassName());
            if(classMetadata.getClassName().contains("dao")){
                return true;
            }
            return false;
        }
    }

      includeFilters :配置扫描的包含规则。其中Filter配置去上面没有差别,但是注意,必须设置 useDefaultFilters = false ,否则默认是true,扫描全路径。

    includeFilters = {
                @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = {UserWoker.class})
            },useDefaultFilters = false

      2.3、Bean的作用域

        2.3.1、默认,在不指定@Scope的情况下,bean是单例的,并且是饿汉式加载,即容器启动的时候,就创建实例。
    @Configuration
    public class MainConfig {
        @Bean
        public Person person(){
            return new Person();
        }
    }
         2.3.2、指定@Scope为 prototype 表示多实例,懒汉式加载,即容器启动的时候不会创建实例,在第一次使用的时候才会去创建。
    @Configuration
    public class MainConfig {
        /**
         *  Scope 配置bean作用域,默认单例模式:
         *      prototype - 多例模式,并且是懒汉式加载,在IOC容器启动的时候,不会创建对象,在第一次使用的时候才去创建
         *      singleton - 单例模式,默认饿汉式加载,在IOC启动的时候就创建对象
         */
        @Bean
        @Scope(scopeName = "prototype")
        public Person initPerson(){
            return new Person();
        }
    }    
         2.3.3、@Scope 取值:singleton-单例(默认)、prototype-多实例、request-同一个请求、session-同一个会话

      2.4、懒加载

      懒加载@Lazy主要针对的是单例bean,容器启动的时候,不创建对象,第一次使用的时候才去创建。

    @Configuration
    public class MainConfig {
    
        /**
         *  Lazy 配置bean时候懒加载,与 Scope.singleton单例来配合上使用,容器启动的时候不创建对象,第一次使用的时候才去创建对象
         */
        @Bean
        @Lazy
        public Person initPerson(){
            return new Person();
        }
    }

      2.5、@Conditional条件判断

      存在某个组件或者不存在某个组件的时候,才去加载或者不加载bean。Springboot体系中,大量使用到的机制,通常如 @ConditionalOnBean、@ConditionalOnClass 等。

    
        @Override
        public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
            if(null != context.getBeanFactory().getBean(UserLog.class)){
                return true;
            }
            return false;
        }
    }
    @Configuration
    public class MainConfig {
    
    //    @Bean("userLog")
        public UserLog initUserLog(){
            return new UserLog();
        }
    
        /**
         * 当容器中有 userLog 组件的时候,才去实例化当前bean
         */
        @Bean
        @Conditional(value = {Userconditional.class})
    //    @ConditionalOnBean(value = {UserLog.class})
        public UserAspect initUseraspect(){
            return new UserAspect();
        }
    }

      2.6、IOC容器中添加组件的方法

        2.6.1、@ComponentScan + @Contoller @Service @Respository @Component, 自己写的组件,可以通过此种方式导入

        2.6.2、@Bean导入组件,适用于第三方组件的类

        2.6.3、@Import导入组件,导入的组件id为类名全路径。

    @Configuration
    @Import(value = {Person.class, Car.class, DogImportSelector.class, CatBeanDefiniitionRegister.class})
    public class MainConfig {
    
    }
    
    public class DogImportSelector implements ImportSelector {
    
        @Override
        public String[] selectImports(AnnotationMetadata importingClassMetadata) {
            return new String[]{"com.cfang.ioc.tImport.Dog"};
        }
    }
    
    public class CatBeanDefiniitionRegister implements ImportBeanDefinitionRegistrar {
    
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            //创建bean定义对象
            RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();
            rootBeanDefinition.setBeanClass(Cat.class);
            //bean定义对象注册到容器中,并设置beanName
            registry.registerBeanDefinition("cat2", rootBeanDefinition);
        }
    }

         2.6.4、通过FactoryBean注册组件

    @Configuration
    public class MainConfig {
    
        @Bean("personFactoryBean")
        public PersonFactoryBean initBean(){
            return new PersonFactoryBean();
        }
    }
    
    public class PersonFactoryBean implements FactoryBean<Person> {
        /**
         * 返回bean对象
         */
        @Override
        public Person getObject() throws Exception {
            return new Person();
        }
        /**
         * 设置bean类型
         */
        @Override
        public Class<?> getObjectType() {
            return Person.class;
        }
        /**
         * 是否单例
         */
        @Override
        public boolean isSingleton() {
            return false;
        }
    }

       2.7、Bean的初始化和销毁方法

        2.7.1、生命周期

          bean实例化创建 -----> 初始化 -------> use  -------->销毁方法。

          可通过指定bean的初始化init 和销毁destroy方法

    @Configuration
    @ComponentScan(value = {"com.cfang.ioc.lifecycle"})
    public class MainConfig {
        @Bean(initMethod = "init", destroyMethod = "destroy")
        public Car car(){
            return new Car();
        }
    }

          单例bean,容器启动的是,bean就创建了,容器关闭的时候,也会调用对应的销毁bean方法。

          多例bean,容器启动的是,不创建,第一次使用的时候去创建,bean的销毁也不受IOC容器管理。

        2.7.2、实现 InitializingBean, DisposableBean

    @Component
    public class Book implements InitializingBean, DisposableBean {
        public Book(){
            System.out.println("Book构造方法...");
        }
        @Override
        public void destroy() throws Exception {
            System.out.println("DisposableBean.destory....");
        }
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("InitializingBean.afterPropertiesSet....");
        }
    }

        2.7.3、@PostConstruct、@PreDestroy注解

    @Component
    public class Person {
        public Person(){
            System.out.println("Person构造方法...");
        }
        @PostConstruct
        public void init(){
            System.out.println("Person PostConstruct...");
        }
        @PreDestroy
        public void destroy(){
            System.out.println("Person destroy...");
        }
    }

         2.7.4、实现 BeanPostProcessor,bean后置处理器,可拦截bean创建过程

            postProcessBeforeInitialization - 在 init 方法之前调用

            postProcessAfterInitialization - 在 init 方法之后调用

    @Component
    public class TBeanPostProcessor implements BeanPostProcessor {
    
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("TBeanPostProcessor.postProcessBeforeInitialization ..." + beanName);
            return bean;
        }
    
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("TBeanPostProcessor.postProcessAfterInitialization ..." + beanName);
            return bean;
        }
    }

       2.8、属性主键赋值 @Value + @PropertySource

    public class Person {
    
        @Value("商业")
        private String name;
        @Value("#{28-8}")
        private Integer year;
        @Value("${name}")
        private String lname;
    
        @Override
        public String toString() {
            return name + lname + year;
        }
    }
    
    @Configuration
    @PropertySource(value = {"classpath:bean.properties"})
    public class MainConfig {
    
        @Bean("person")
        public Person initBean(){
            return new Person();
        }
    }
  • 相关阅读:
    Swift 网络请求数据与解析
    第三方-Swift2.0后Alamofire的使用方法
    java异常处理机制throws
    eclipse导入不到嵌套的项目
    java异常处理机制Exception
    在eclipse中查找指定文件
    mysql查询count
    【待解决】An internal error occurred during: "Launching baiduTest1". java.lang.NullPointerException
    TestNG升级
    eclipse安装TestNG插件
  • 原文地址:https://www.cnblogs.com/eric-fang/p/13707086.html
Copyright © 2011-2022 走看看