• 四、spring成长之路——springIOC容器(下)


    5.spring注解开发(Spring扩展知识)

    5.1定义配置类:@Configuration 声明一个类为IOC容器 @Bean定义一个Bean

    package com.itcloud.annotation;
    
    
    import com.itcloud.pojo.Student;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class CommonConfig {
        @Bean
        public Student student(){
            Student student = new Student();
            student.setId(10l);
            student.setName("configuration");
            return student;
        }
    }
    

    测试

    package com.itcloud.pojo.anntation;
    
    import com.itcloud.annotation.CommonConfig;
    import com.itcloud.pojo.Student;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    
    public class AnnotationTest {
        ApplicationContext context = new AnnotationConfigApplicationContext(CommonConfig.class);
        @Test
        public void testAnnotation(){
            Student stu = context.getBean(Student.class);
        }
    }
    

    注解@ComponmentScan使用详解,该注解作用在类上面

    @ComponentScan(value = "com.itcloud",useDefaultFilters = false,includeFilters = {
            @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {
                    Component.class, Service.class, Repository.class
            })
    },excludeFilters = {
            @ComponentScan.Filter(type=FilterType.ANNOTATION,classes = {
                    Controller.class
            })
    })
    

    bean的作用域,@Scope定义在方法上面

    /**
         * 取值:singleton:默认值,单实例,容器加载的时候进行bean的创建
         *      prototype:允许创建多个对象,使用的时候进行队形的创建
         */
        @Scope(value = "")
    

    bean的懒加载,@Lazy放在方法上面,在没有这个注解的时候,bean会在容器启动的时候进行加载,但是这个注解使用之后,当使用到这个bean的时候才会进行性bean的加载。

    5.2.按照条件进行注入

    @Conditional该注解可以根据条件进行注入操作,作用类或者方法上面

    自定义判断条件:此判断条件主要的作用是判断容器中是否存在studentbean,如果存在则注入teacher,否则不注入;

    package com.itcloud.annotation.conditional;
    
    import org.springframework.beans.factory.support.BeanDefinitionRegistry;
    import org.springframework.context.annotation.Condition;
    import org.springframework.context.annotation.ConditionContext;
    import org.springframework.core.type.AnnotatedTypeMetadata;
    
    public class MyConditional implements Condition {
        @Override
        public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
            BeanDefinitionRegistry registry = context.getRegistry();
            boolean student = registry.containsBeanDefinition("student");
            if(student){
                return true;
            }
            return false;
        }
    }
    
    	@Bean("teacher")
        @Conditional({MyConditional.class})
        public Teacher teacher(){
            Teacher t = new Teacher();
            t.setId(10l);
            t.setName("李老师");
            return t;
        }
    

    5.3.@Import注解进行注入

    具体用法:按照注解的意思我们可以导入一个ioc容器,ImportSelector或者ImportBeanDefinitionRegistrar的子类,再或者是一个普通的组件类,即被@Component相关注解修饰的类,那么普通的类可以吗?

    /**
    	 * {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar}
    	 * or regular component classes to import.
    	 */
    

    //在这之前我们自定义了一个Color类

    @Configuration
    @Import({Color.class})
    public class CommonConfig {...}
    

    经过测试普通类也是可以导入的,但是普通类的bean默认的value是全类名:com.itcloud.annotation.vo.Color

    ImportSelector测试

    自定义一个MyImportSelector.java类实现ImportSelector接口,把需要导入的类通过字符串数组的形式进行返回,一定要是全类名

    参数AnnotationMetadata可以获取IOC容器上面的注解

    package com.itcloud.annotation.myimport;
    
    import org.springframework.context.annotation.ImportSelector;
    import org.springframework.core.type.AnnotationMetadata;
    
    public class MyImportSelector implements ImportSelector {
    
        @Override
        public String[] selectImports(AnnotationMetadata importingClassMetadata) {
            return new String[]{"com.itcloud.annotation.vo.Blue","com.itcloud.annotation.vo.Red"};
        }
    }
    
    

    ImportBeanDefinitionRegistrar测试

    package com.itcloud.annotation.myimport;
    
    import com.itcloud.annotation.vo.Yellow;
    import org.springframework.beans.factory.support.BeanDefinitionRegistry;
    import org.springframework.beans.factory.support.RootBeanDefinition;
    import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
    import org.springframework.core.type.AnnotationMetadata;
    
    public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            //这里可以进行bean的注册
            RootBeanDefinition beanDefinition = new RootBeanDefinition(Yellow.class);
            registry.registerBeanDefinition("yellow", beanDefinition);
        }
    }
    

    5.4、FactoryBean注入

    在2>2.7里面已经说过了,此处不再赘述:点击跳转

    bean的生命周期,在注解中的表现如下:

    ​ 和xml配置文件相似;

    @Bean(value = "student",initMethod = "init",destroyMethod = "destory")
    

    5.5、后置处理详解

    1.注解:@PostConstruct@PreDestory

    ​ 在这里一定要将此类注入到容器中,至于怎么注入,就不再赘述

    package com.itcloud.annotation.vo;
    
    import org.springframework.stereotype.Component;
    
    import javax.annotation.PostConstruct;
    import javax.annotation.PreDestroy;
    
    
    @Component
    public class PostBean {
    
        public PostBean(){
            System.out.println("构造方法执行.....");
        }
    
        @PostConstruct
        public void postConstruct(){
            System.out.println("postConstruct......");
        }
    
    
        @PreDestroy
        public void destroy(){
            System.out.println("容器关闭之前执行的吗......");
        }
    }
    
    

    测试结果:

    <!--
    	构造方法执行.....
    	postConstruct......
    	## 容器关闭之前执行如下
    	容器关闭之前执行的吗......
    -->
    

    2.两个接口 InitializingBean DisposableBean

    package com.itcloud.annotation.vo;
    
    import org.springframework.beans.factory.DisposableBean;
    import org.springframework.beans.factory.InitializingBean;
    
    public class PostProcessorBean implements InitializingBean, DisposableBean {
    
    
        public PostProcessorBean(){
            System.out.println("PostProcessorBean.....构造方法执行");
        }
    
        @Override
        public void destroy() throws Exception {
            System.out.println("PostProcessorBean.......destroy()");
        }
    
        //属性设置完成之后执行,构造方法之后调用
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("PostProcessorBean.......afterPropertiesSet()");
        }
    }
    
    

    3.BeanPostProcessor原理解析

    在前面后置处理器中我们已经了解了,通过实现接口BeanPostProcessor可以进行后置处理,在这里我们将要对后置处理原理进行简单的介绍

    ​ 定义一个后置处理器

    ​ 这个处理器会在所有bean创建的时候,构造方法之后执行,所有初始化方法之前执行,而方法postProcessAfterInitialization会在初始化之后调用,不需要容器关闭

    package com.itcloud.processor;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    import org.springframework.stereotype.Component;
    
    @Component
    public class MyProcessor implements BeanPostProcessor{
    
    
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("Before*****beanName = " + beanName +"-----bean = " + bean);
            return bean;
        }
    
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("After*****beanName = " + beanName +"----bean = " + bean);
            return bean;
        }
    }
    
    
    package com.itcloud.processor;
    
    
    import com.itcloud.annotation.vo.Color;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.FilterType;
    import org.springframework.stereotype.Component;
    
    @Configuration
    @ComponentScan(useDefaultFilters = false, includeFilters = {
            @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {
                    Component.class
            })
    })
    public class ProcessorConfig {
    
        @Bean
        public Color color(){
    
            return new Color();
        }
    }
    
    

    源码解析:

    5.6、属性赋值和自动装配

    1.@Value的使用

    package com.itcloud.annotation.vo;
    
    
    import org.springframework.beans.factory.annotation.Value;
    
    public class Color {
    
        //直接赋值
        @Value("red")
        private String type;
    
        //EL表达式
        @Value("#{100.30-13.43}")
        private Double length;
    
        //引用外部属性文件
    
        @Value("${value.username}")
        private String username;
    
        @Value("${value.password}")
        private String password;
    }
    

    在配置类上面一定要引用外部文件,通过注解@PropertySource

    package com.itcloud.processor;
    
    
    import com.itcloud.annotation.vo.Color;
    import org.springframework.context.annotation.*;
    import org.springframework.stereotype.Component;
    
    @Configuration
    @ComponentScan(useDefaultFilters = false, includeFilters = {
            @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {
                    Component.class
            })
    })
    @PropertySource("classpath:/properties/value.properties")
    public class ProcessorConfig {
    
        @Bean
        public Color color(){
    
            return new Color();
        }
    }
    
    

    通过环境变量来获取属性的值

    Environment environment = context.getEnvironment();
    String property = environment.getProperty("value.username");
    

    2.自动装配使用的注解

    2.1、spring注解:@Autowired前面我们已经说过,这个注解可以配合@Qualifier使用,明确调用使用特定的Bean

    ​ @Autowired也可以配置@Primary注解使用,当类型相同的使用,会优先选择@Primary注解标识的 bean

    2.2.非spring注解:@Resource按照名称注入,@Inject,@Autowired用法类似,需要引入jar:

    <dependency>
        <groupId>javax.inject</groupId>
        <artifactId>javax.inject</artifactId>
        <version>1</version>
    </dependency>
    

    5.6.在类中使用spring底层的组件

    如果一个类想要使用spring底层的组件,可以实现一些接口xxxAware,这个接口都是org.springframework.beans.factory.Aware接口的子类

    1.xxxAware方法的使用

    package com.itcloud.annotation.vo;
    
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.BeanNameAware;
    import org.springframework.context.*;
    import org.springframework.core.env.Environment;
    import org.springframework.util.StringValueResolver;
    
    public class Color implements ApplicationContextAware, BeanNameAware, EmbeddedValueResolverAware {
        private ApplicationContext context;
    
    
        public void userContext(){
            Environment environment = this.context.getEnvironment();
            String property = environment.getProperty("value.url");
            System.out.println(property);
    
        }
    
    
        //获取applicationContext对象
        @Override
        public void setApplicationContext(ApplicationContext context) throws BeansException {
            this.context = context;
        }
    
        //获取当前bean的name
        @Override
        public void setBeanName(String name) {
            System.out.println("name===" + name);
        }
    
    
        //进行字符串的解析
        @Override
        public void setEmbeddedValueResolver(StringValueResolver resolver) {
            String result = resolver.resolveStringValue("数据库的名称:${value.username}, el表达式解析:#{10-3*3}");
            System.out.println(result);
        }
    }
    
    5.6.@Profile的使用

    此注解既可以使用在bean上,也可以定义在一个IOC容器上面,激活的方式:

    ​ 1.类激活

    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
    ctx.getEnvironment().setActiveProfiles("development");
    ctx.register(SomeConfig.class, StandaloneDataConfig.class, JndiDataConfig.class);
    ctx.refresh();
    

    ​ 2.jvm参数激活:

    -Dspring.profiles.active="profile1,profile2"
    
  • 相关阅读:
    电话聊天狂人
    PAT 1080. MOOC期终成绩
    PAT 1079. 延迟的回文数
    [转载]matlab 中序列求极值的方法
    [转载][转]Matlab-寻找峰值函数
    [转载]Kirchhoff Migration Impulse Response
    Envelope Extraction Using the Analytic Signal
    [转载]地震动的挑选
    C笔记
    Git常用有用命令
  • 原文地址:https://www.cnblogs.com/hu1056043921/p/8878302.html
Copyright © 2020-2023  润新知