Chapter 3 Advanced Assembly


1. "profile bean" (the configuration provided by Spring for those beans that are related to the running environment. After configuration, Spring will select the corresponding bean according to the running environment)
(you need to put these beans in the profile bean and ensure that the profile is active Status)
2. Use java to configure the profile bean (use the @Profile annotation to specify which profile file the bean belongs to)
For example:
// use profile bean     @Configuration on class level

    @profile( "dev" )
     public  class configuration class {
        @Bean
        public required Bean method name(){
             new required Bean();
        }
    }
    (Similarly: you can create another class to specify beans that need to be assembled in different environments) 
//The above bean is only created when the dev profile file is activated. Create is ignored if dev is not active. (Assemble different beans according to whether the profile is activated or not)
3. Use profile beans at the method level (from Spring 3.2, you can use Profile beans at the method level)
    @Configuration
     public  class configuration class name {
        @Bean
        @Profile( "dev")       // Bean method name required by the public development environment for the bean assembled by the dev profile 
        (){
             return Bean() required by the new development environment; 
        }
        @Bean
        @Profile( "prod")         // Beans assembled by prod profile Bean method name required by 
        public runtime environment(){
             return Bean() required by  new runtime environment;
        }
    }
4. Configure Profile 1 in XML 
: Add profile = "" to the <beans> element of each xml configuration file.
For example:
            <beans xmlns = ""
                   ...
                   profile = "dev">
                   <bean>...<bean>
            </bean>            
    2: Use nested <beans> 
eg:
            <beans>
                <beans profile = "dev">
                    <bean>...<bean>
                </beans>
                <beans profile = "prod">
                    <bean>...<bean>
                </beans>
            <beans>    
5. Activate the profile 
to configure the two properties of the profile:
1: active (Spring.profiles.active): specify that the profile is active
2: default (Spring.profiles.default): If active is not configured, it will find the value of the default configuration .
//If both active and default are not configured: Do not assemble the beans in the profile.
Set the active and default attributes:
1: Initialize as a parameter of DispatcherServlet
Add in the Servlet configuration of the web:
                <web-app ...>
                    <context-param>
                        <param-name>spring.profiles.default</param-name>
                        <param-value>dev</param-value>
                    </context-parm>
                </web-app>
        2: As the context of the web application 
3: As a JNDI entry
4: As an environment variable
5: As a system property of the JVM
6: On the integration test class, use the @activeProfiles annotation to set
6. Conditional bean
requirements: I want a bean that contains An external jar is created only after a specific bean is declared, (in short, the conditional creation of beans)
is difficult to do before Spring 4. But Spring 4 introduced the @Conditional annotation, which can be used on methods annotated with @Bean.
@Conditional:
The bean is created if the given evaluates to true, otherwise the bean is ignored.
For example:
// Let's say there is a class called MagicBean and we want this bean to be instantiated only when the environment property magic is set.
1: Conditionally create a bean:
            @bean
            @Conditional(MagicExistsCondition.class ) //     Set the condition. 
            public MagicBean magicBean(){
                 return  new MagicBean();
            }
            // The parameter passed to @Conditional needs to be the implementation of the Condition interface. To implement the Condition interface, you only need to implement the matches() method.
                 // The return value of the matches() method is the result of the judgment condition.
        2: Judgment conditions:
            public class MagicExistsCondition implements Condition{
                public boolean matches(ConditionContext context , AnnotatedTypeMetadata metadata){
                    Environment env = context.getEnvironment();
                    return env.containsProperty("magic");
                }
            }
            // In this example, determine whether there is magic in the environment.
        Note: 
The above example just uses the ConditionContext to get the environment properties. In actual development, the acquisition will be judged according to the more responsible content (but the source is basically the parameters of matches):
ConditionContext:
1: Use the BeanDefinitionRegistry returned by the getRegistry() method to check the definition of the bean.
2: Use the ConfigurableListtableBeanFactory() returned by the getBeanFactory() method to check whether the bean exists and detect the properties of the bean.
3: Use the ResourceLoader returned by the getEnvironment() method to load resources.
4: Use the ClassLoader returned by getClassLoader() to load and detect whether the class exists.
AnnotatedTypeMetadata:
This interface can check what annotations are included on the method with @Bean.
1: Use the isAnnotated() method to determine whether the method with @Bean has other annotations.
2: With the help of other methods, other annotations and their properties on the method can be checked.
7. Dealing with the ambiguity of automatic assembly During
automatic assembly: only one Bean can be assembled successfully when it matches the required result. Matching multiple Beans hinders automatic assembly.
E.g:
        //需要自动装配的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表达式语言
????????????????

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324471614&siteId=291194637