美文网首页干货分享
Java分析之Spring bean注入

Java分析之Spring bean注入

作者: 小白菜aaa | 来源:发表于2020-09-15 20:18 被阅读0次

    前言

    本文主要介绍Spring bean注入的大概过程,废话不多说让我们进入正文。

    使用配置注入对象

    向beans.xml注入bean:

    <bean id="person" class="com.enjoy.cap1.Person">
        <property name="name" value="james"></property>
        <property name="age" value="19"></property>
    </bean>
    
    

    获取bean

    //把beans.xml的类加载到容器
    ApplicationContext app = new ClassPathXmlApplicationContext("beans.xml");
    //从容器中获取bean
    Person person = (Person) app.getBean("person");
    
    

    使用配置类注入对象

    @Configuration
    public class MainConfig {
        //给容器中注册一个bean, 类型为返回值的类型, 
        @Bean("abcPerson")
        public Person person01(){
            return new Person("james",20);
        }
    }
    
    

    获取bean

    //把配置类中的bean加载到容器
    ApplicationContext app = new AnnotationConfigApplicationContext(MainConfig.class);
    //从容器中获取bean,只用@Bean 则 bean ID 默认取方法名,即person01
    Person person = (Person) app.getBean("abcPerson");
    
    

    使用注解注入对象

    配置类添加扫面包注解,将指定包中的类加载到容器

    @Configuration
    @ComponentScan(value="com.enjoy.cap2")
    public class Cap2MainConfig {
        //给容器中注册一个bean, 类型为返回值的类型, 
        @Bean
        public Person person01(){
            return new Person("james",20);
        }
    }
    
    

    添加注解

    @Controller
    public class OrderController { }
    
    @Service
    public class OrderService { }
    
    @Repository
    public class OrderDao{ }    
    
    

    获取bean

    //把配置类中的bean加载到容器
    ApplicationContext app = new AnnotationConfigApplicationContext(Cap2MainConfig.class);
    //Spring 容器中所有 JavaBean 的名称,注解不指定bean ID 则默认取类名,且首字母小写
    String[] beanDefinitionNames = app.getBeanDefinitionNames();
    
    

    配置类添加扫描包注解,将指定包中的类加载到容器

    @Configuration
    @ComponentScan(value="com.enjoy.cap2")
    public class Cap2MainConfig {
        //给容器中注册一个bean, 类型为返回值的类型, 
        @Bean
        public Person person01(){
            return new Person("james",20);
        }
    }
    
    

    添加注解

    @Controller
    public class OrderController { }
    
    @Service
    public class OrderService { }
    
    @Repository
    public class OrderDao{ }    
    
    

    获取bean

    //把配置类中的bean加载到容器
    ApplicationContext app = new AnnotationConfigApplicationContext(Cap2MainConfig.class);
    //Spring 容器中所有 JavaBean 的名称,注解不指定bean ID 则默认取类名,且首字母小写
    String[] beanDefinitionNames = app.getBeanDefinitionNames();
    
    

    定制包扫描时的过滤规则

    //@ComponentScan value:指定要扫描的包
    //excludeFilters = Filter[] 指定扫描的时候按照什么规则排除那些组件
    //includeFilters = Filter[] 指定扫描的时候只需要包含哪些组件
    //useDefaultFilters = false 默认是true,扫描所有组件,includeFilters 要改成false,excludeFilters则是true
    //----扫描规则如下
    //FilterType.ANNOTATION:按照注解
    //FilterType.ASSIGNABLE_TYPE:按照给定的类型;比如按BookService类型
    //FilterType.ASPECTJ:使用ASPECTJ表达式
    //FilterType.REGEX:使用正则指定
    //FilterType.CUSTOM:使用自定义规则,自已写类,实现TypeFilter接口
    
    @Configuration
    @ComponentScan(value = "com.enjoy.cap2", includeFilters = {
        @Filter(type = FilterType.ANNOTATION, classes = {Controller.class}),
        @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {OrderService.class})
    }, useDefaultFilters = false)
    public class Cap2MainConfig { }
    
    @Configuration
    @ComponentScan(value="com.enjoy.cap2",excludeFilters={
            @Filter(type = FilterType.ANNOTATION, classes = {Controller.class}),
            @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {OrderService.class})
    })
    public class Cap2MainConfig { }
    
    

    添加注解

    @Controller
    public class OrderController { }
    
    @Service
    public class OrderService { }
    
    @Repository
    public class OrderDao{ }    
    
    

    获取bean

    //把配置类中的bean加载到容器
    ApplicationContext app = new AnnotationConfigApplicationContext(Cap2MainConfig.class);
    //Spring 容器中所有 JavaBean 的名称,注解不指定bean ID 则默认取类名,且首字母小写
    String[] beanDefinitionNames = app.getBeanDefinitionNames();
    
    

    FilterType.CUSTOM的例子

    public class JamesTypeFilter implements TypeFilter {
        private ClassMetadata classMetadata;
    
        /*
         * MetadataReader:读取到当前正在扫描类的信息
         * MetadataReaderFactory:可以获取到其他任何类信息
         */
        public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
                throws IOException {
            //获取当前类注解的信息
            AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
            //获取当前正在扫描的类信息
            classMetadata = metadataReader.getClassMetadata();
            //获取当前类资源(类的路径)
            Resource resource = metadataReader.getResource();
            String className = classMetadata.getClassName();
            System.out.println("----->" + className);
            if (className.contains("Order")) {//当类包含er字符, 则匹配成功,返回true
                return true;
            }
            return false;
        }
    }
    
    @Configuration
    @ComponentScan(value="com.enjoy.cap2",includeFilters={
            @Filter(type=FilterType.CUSTOM,classes={JamesTypeFilter.class})
    },useDefaultFilters=false)
    public class Cap2MainConfig { }
    
    

    添加注解

    @Controller
    public class OrderController { }
    
    @Service
    public class OrderService { }
    
    @Repository
    public class OrderDao{ }    
    
    

    获取bean

    //把配置类中的bean加载到容器
    ApplicationContext app = new AnnotationConfigApplicationContext(Cap2MainConfig.class);
    //Spring 容器中所有 JavaBean 的名称,注解不指定bean ID 则默认取类名,且首字母小写
    String[] beanDefinitionNames = app.getBeanDefinitionNames();
    
    

    单例多例

    @Configuration
    public class Cap3MainConfig {
        //给容器中注册一个bean, 类型为返回值的类型, 默认是单实例
        @Bean
        public Student student(){
            return new Student("jack",20);
        }
    
        /*
         * prototype:多实例: IOC容器启动的时候,IOC容器启动并不会去调用方法创建对象, 而是每次获取的时候才会调用方法创建对象
         * singleton:单实例(默认):IOC容器启动的时候会调用方法创建对象并放到IOC容器中,以后每次获取的就是直接从容器中拿(大Map.get)的同一个bean
         * request: 主要针对web应用, 递交一次请求创建一个实例
         * session:同一个session创建一个实例
         */
        @Scope("prototype")
        @Bean
        public Person person(){
            return new Person("james",20);
        }
    }
    
    

    验证

        AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap3MainConfig.class);
        //从容器中分别取两次person实例, 看是否为同一个bean
        Object bean1 = app.getBean("person");
        Object bean2 = app.getBean("person");
        System.out.println(bean1 == bean2);
        //从容器中分别取两次student实例, 看是否为同一个bean
        Object student1 = app.getBean("student");
        Object student2 = app.getBean("student");
        System.out.println(student1 == student2);
    
    

    延迟加载

    @Configuration
    public class Cap4MainConfig {
        /*
         * 懒加载: 主要针对单实例bean:默认在容器启动的时候创建对象
         * 懒加载:容器启动时候不创建对象, 仅当第一次使用(获取)bean的时候才创建被初始化
         */
        @Lazy
        @Bean
        public Person person(){
            System.out.println("给容器中添加person.......");
            return new Person("james",20);
        }
    }
    
    

    验证

    AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap4MainConfig.class);
    System.out.println("IOC容器创建完成........");
    app.getBean("person");//执行获取的时候才创建并初始化bean
    
    

    @Conditional条件注册bean

    @Configuration
    public class Cap5MainConfig {
        @Bean("person")
        public Person person(){
            System.out.println("给容器中添加person.......");
            return new Person("person",20);
        }
    
        @Conditional(WinCondition.class)
        @Bean("lison")
        public Person lison(){
            System.out.println("给容器中添加lison.......");
            return new Person("Lison",58);
        }
    
        @Conditional(LinCondition.class)
        @Bean("james")
        public Person james(){
            System.out.println("给容器中添加james.......");
            return new Person("james",20);
        }
    }
    
    public class WinCondition implements Condition{
        /**
         *
         * @param context ConditionContext: 判断条件可以使用的上下文(环境)
         * @param metadata AnnotatedTypeMetadata: 注解的信息
         * @return
         */
        public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
            // TODO 是否为WINDOW系统
            //能获取到IOC容器正在使用的beanFactory
            ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
            //获取当前环境变量(包括我们操作系统是WIN还是LINUX??)
            Environment environment = context.getEnvironment();
            String osName = environment.getProperty("os.name");
            if(osName.contains("Windows")){
                return true;
            }
            return false;
        }
    }
    
    public class LinCondition implements Condition{
        public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
            // TODO 是否为WINDOW系统
            //能获取到IOC容器正在使用的beanFactory
            ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
            //获取当前环境变量(包括我们操作系统是WIN还是LINUX??)
            Environment environment = context.getEnvironment();
            String osName = environment.getProperty("os.name");
            if(osName.contains("linux")){
                return true;
            }
            return false;
        }
    }
    
    

    验证

    //通过打印语句判断配置是否生效
    AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap5MainConfig.class);
    System.out.println("IOC容器创建完成........");
    

    结尾

    感谢看到最后的朋友,都看到最后了,点个赞再走啊,如有不对之处还请多多指正。

    相关文章

      网友评论

        本文标题:Java分析之Spring bean注入

        本文链接:https://www.haomeiwen.com/subject/ghstyktx.html