zoukankan      html  css  js  c++  java
  • 第3章 高级装配


    1、"profile bean"(Spring为那些和运行环境有关系的bean提供的配置。配置后,Spring会根据运行环境选取相应的bean)
    (需要将这些bean放到profile bean中,并确保profile处于active状态)
    2、使用java配置profile bean(使用@Profile注解指定bean属于哪个profile文件中)
    例如:
    //在类级别上使用profile bean
        @Configuration
        @profile("dev")
        public class 配置类{
            @Bean
            public 需要的Bean 方法名(){
                new 需要的Bean();
            }
        }
        (同理:可以再创建一个类指定不同环境需要装配的bean)
    //上面这个bean只有在dev profile文件被激活时才创建。如果dev 不是激活状态则忽略创建。(根据profile是否激活,装配不同的bean)
    3、在方法级别上使用profile bean (Spring 3.2 开始可以再方法级别上使用Profile bean)
        @Configuration
        public class 配置类名{
            @Bean
            @Profile("dev")      //dev profile 装配的bean
            public 开发环境需要的Bean 方法名(){
                return new 开发环境需要的Bean();
            }
            @Bean
            @Profile("prod")        //prod profile 装配的bean
            public 运行环境需要的Bean 方法名(){
                return new 运行环境需要的Bean();
            }
        }
    4、在XML中配置Profile
    1:每一个xml配置文件的<beans>元素添加 profile = ""
    例如:
                <beans xmlns = ""
                       ...
                       profile = "dev">
                       <bean>...<bean>
                </bean>            
        2:使用嵌套<beans>
    例如:
                <beans>
                    <beans profile = "dev">
                        <bean>...<bean>
                    </beans>
                    <beans profile = "prod">
                        <bean>...<bean>
                    </beans>
                <beans>    
    5、激活profile
    配置profile的两个属性:
    1:active(Spring.profiles.active):指定那个profile处于激活状态
    2:default(Spring.profiles.default):如果没有配置active,会找default配置的值。
    //如果都active和default都没有配置:不装配profile中的bean。
    设置active和default属性:
    1:作为DispatcherServlet的参数初始化
    在web的Servlet配置中加:
                    <web-app ...>
                        <context-param>
                            <param-name>spring.profiles.default</param-name>
                            <param-value>dev</param-value>
                        </context-parm>
                    </web-app>
            2:作为Web应用的上下文
    3:作为JNDI条目
    4:作为环境变量
    5:作为JVM的系统属性
    6:在集成测试类上,使用@activeProfiles注解设置
    6、条件化的bean
    需求:希望一个bean在含有某个外部的jar是才创建,希望某个特定的bean声明后才创建,(总之就是有条件的创建bean)
    在Spring 4之前很难做到。但是Spring 4 引入了 @Conditional 注解,他可以用在带有@Bean的注解方法上。
    @Conditional:
    如果给定的计算结果为true则创建bean,否则bean被忽略。
    例如:
    //假设有一个名为 MagicBean 的类,我们希望只有设置了环境属性 magic 时才实例化这个bean。
    1:条件话创建bean:
                @bean
                @Conditional(MagicExistsCondition.class)    //设置条件。
                public MagicBean magicBean(){
                    return new MagicBean();
                }
                //传给@Conditional的参数需要是Condition接口的实现。实现Condition接口只需要实现matches()方法,
                    //matches()方法返回值就是判断条件的结果。
            2:判断条件:
                public class MagicExistsCondition implements Condition{
                    public boolean matches(ConditionContext context , AnnotatedTypeMetadata metadata){
                        Environment env = context.getEnvironment();
                        return env.containsProperty("magic");
                    }
                }
                //本例中判断环境中是否有magic。
            注意:
    上面的例子只是使用了ConditionContext获取到了环境属性。实际开发中获取会根据更为负责的内容判断(但来源基本都是matches的参数):
    ConditionContext:
    1:使用getRegistry()方法返回的BeanDefinitionRegistry检查bean的定义。
    2:使用getBeanFactory()方法返回的ConfigurableListtableBeanFactory()检查bean是否存在,探测bean的属性。
    3:使用getEnvironment()方法返回的ResourceLoader加载资源。
    4:使用getClassLoader()返回的ClassLoader加载并检测类是否存在。
    AnnotatedTypeMetadata:
    这个接口可以检查带有@Bean的方法上还含有什么注解。
    1:使用isAnnotated()方法可以判断带有@Bean的方法是不是还有别的注解。
    2:借助别的方法可以检查方法上的其他注解及其属性。
    7、处理自动装配的歧义性
    自动装配时:只有一个Bean匹配到所需结果时才能装配成功,匹配到多个Bean阻碍了自动装配。
    例如:
            //需要自动装配的bean
            @Autowired
            public void setDessert(Dessert dessert){
                this.dessert = dessert;
            }
            //Dessert 是一个接口。并且有三个类实现了该接口并且都是用@Component指定了该类作为bean:
            @Component
            public class Cake implements Dessert{...}
            @Component
            public class Cookies implements Dessert{...}
            @Component
            public class IceCream implements Dessert{...}
            //当Spring试图给setDessert进行自动注入时:无法匹配到唯一的bean,抛出异常(NoUniqueBeanDefinitionException)。
    虽然出现这种歧义性的概率非常小,当发生这种情况时我们可以通过
    1:给其中一个bean设置首选。2:使用限定符将可选的bean缩小的一个。
    8、标注首选的bean
    在声明bean的时候可以使用@Primary设置一个设置首选的bean,当出现自动装配的歧义性时会选择这个bean。
    1:@Component 和 @Primary组合声明首选:
            @Component
            @primary
            public class IceCream implements Dessert{...}
        2:Bean配置 和 Primary组合声明首选:
    2.1:使用javaConfig配置:
                @Bean
                @Primary
                public Dessert iceCream(){
                    return new IceCream();
                }
            2.2:使用xml配置bean(使用XML配置bean同样可以实现:)
                <bean id = "iceCream" class = "" primary = "true" />
            注意:问题来了:如果同时配置了两个Primary,依然产生歧义。(无法最终锁定到一个bean上)
    9、通过限定符将bean范围缩小。
    ????????????????
    10、bean作用域:
    Spring 应用上下文中所有的bean都是以单例的形式创建的,但是每次都调用一个实例是很不现实的(对象状态改变)。
    Spring提供了多种作用域:可以基于这些作用域创建bean:
    1:单例:在整个项目中只有一个bean实例(默认)
    2:原型:每次注入或者通过Spring上下文获取的时候都会创建新的实例
    3:会话:在Web应用中为每一个会话创建一个实例
    4:请求:在Web应用中为每一个请求创建一个实例
    11、选择bean的作用域:
    1:@Component 和 @ Scope 结合
    例如:
                @Component
                @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)     //声明作用域为 原型
                public class xxx(...)
        2:@Bean 和 @Scope 结合(在javaConfig中配置)
    例如:
                @Bean
                @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
                public 需要的Bean 方法名(){
                    return new 需要的Bean();
                }
           使用Xml配置bean的情况:
                <bean id = "" class = "" scope = "prototype" />
    12、使用会话和请求作用域
    ?????????????????
    13、在xml中声明作用域代理
    ?????????????????
    14、运行时值注入:
    之前描述bean时使用了:
    @Bean
    public 需要的Bean 方法名(){return new 需要的Bean();}
    <bean id ="" class = ""><property name = "属性名称" value = "一个字符串"></bean>
    无论是使用什么方法注入,其实都是将关联的内容写死了。这种硬编码有时候是行不通的。
    Spring提供了两种运行时求值的方法。:
    1:属性占位符
    2:Spring表达式语言
    15、注入外部的值:
    在Spring中处理外部值的最简单的办法是声明属性源,并且使用Spring的Environment检索。
    例如:
            @Configuration
            @PropertySource("classPath:/com/xxx/yyy/app.properties")        //声明属性源
            public class 配置类名{
                @Autowired
                Environment env;
                @Bean
                public 需要的Bean 方法名(){
                    return new 需要的Bean(env.getProperty("需要的属性"));    //检索指定的属性
                }
            }
    16、Spring的Environment
    Environment中的getProperty()方法有四个重载的方法:
    1:String getProperty(String key)
    2:String gegtProperty(String key , String defaultValue) //添加了默认值
    3:T getProperty(String key , Class<T> type) //将获取到的值转化为T类型(例如String -> Integer)
    4:T getProperty(String key , Class<T> type , T defaultValue)
    如果没有找到key也没有指定默认值,这种情况需要报告给程序,抛出异常:
    5:getRequiredProperty()
    例如:
                 @Configuration
                 @PropertySource("classPath:/com/xxx/yyy/app.properties")        //声明属性源
                 public class 配置类名{
                     @Autowired
                     Environment env;
                     @Bean
                     public 需要的Bean 方法名(){
                         return new 需要的Bean(env.getRequiredProperty("key"));    //如果找不到,抛出异常(IllegalStateException)
                     }
                 }
        如果想要将属性解析为类:
    6:getPropertyAsClass()
    例如:
                Class<需要的类> clazz = evn.getPropertyAsClass("key" , 需要的类.class);
        Environment还提供了检索哪些profile处于active状态(具体看书)。
    17、解析属性占位符:
    1:在xml中配置:
            <bean id = ""
                class = ""
                c:_title = "${key1}"
                c:_title = "${key2}" />     //${key}将从某一个源获取。
        2:如果使用组件扫描和自动装配(不配置xml了):
            public BlankDisc (@Value("${key}") String title){
                this.title = title;
            }
        注意:
    为了使用占位符,需要配置一个
    PropertyPlaceholderConfigurer bean
    或者
    PropertySourcesPlaceholderConfigurer bean (推荐)
    (具体看书)
    18、使用Spring表达式语言
    ????????????????

  • 相关阅读:
    C#应用程序中的输入法
    201871010128杨丽霞《面向对象程序设计(java)》第六七周学习总结
    201871010128杨丽霞《面向对象程序设计(java)》第一周学习总结
    201871010128杨丽霞《面向对象程序设计(java)》第二周学习总结
    201871010128杨丽霞《面向对象程序设计(java)》第四周学习总结
    201871010128杨丽霞《面向对象程序设计(java)》第七周学习总
    201871010128杨丽霞《面向对象程序设计(java)》第十周学习总结
    201871010128杨丽霞《面向对象程序设计(Java)》第十一周学习总结
    201871010128杨丽霞《面向对象程序设计(java)》第八周学习总结
    201871010128杨丽霞《面向对象程序设计(Java)》第十二周学习总结
  • 原文地址:https://www.cnblogs.com/Xmingzi/p/8856728.html
Copyright © 2011-2022 走看看