约定:

一、@Xxx Class 表示被@Xxx注解的类。同理还有@Xxx注解的字段或方法。

    例如:@Bean Method

  二、@Component Class 同时代指 @Controller、@Service、@Repository。

All beans in a Spring application context are given an ID. -- 如果不指明,也会给定一个默认的ID:类名,首字母小写。
【】上面这句,不适合XML方式,因为XML方式的默认ID是全路径再加上#{n} ,例如 a.b.c.D#2 。

Spring的配置,可以XMLJavaConfig注解

一般推荐使用JavaConfig注解,因为JavaConfig可以保证类型一致,重构重命名都不会影响。

@RunWith(SpringJUnit4ClassRunner.class)    //测试开始时,会自动创建Spring的ApplicationContext。
@ContextConfiguration(classes=CDPlayerConfig.class) // 从什么地方加载JavaConfig。默认导包。

【】Bean在第三方库中时,无法使用注解扫描导入~    
        这时,可以使用JavaConfig或者XML配置。但是,建议使用JavaConfig配置,因为更强大,且类型有保证。
            JavaConfig is configuration code。就是说,它不应该包含任何业务代码,也不应该被任何业务代码包含。

【】@Autowired 可以用在任何方法上,本质都是注入形参
【】@Autowired(required=false) 这样注入失败不会异常!    但是需要判断null异常
【】问题:如果有多个bean,那怎么选择?同时满足也会异常,需要窄化范围,见后面。

@Component     基本等同于     @Named   (JSR330)
@Autowired   基本等同于 @Inject  (JSR330)

纯JavaConfig:

JavaConfig 就是@Configuration Class。

如果JavaConfig需要自动扫描并创建Bean那就再加上@ComponentScan注解。

  注意,这里的扫描对象是@Component Class 。

  而且,自动生成的Bean,其ID就是类名,首字母小写。(XML则是全路径再加上#{n} ,例如 a.b.c.D#2 。)

  示例如下:

@Configuration     // 声明这是JavaConfig,Spring会自动加载
@ComponentScan() // 自动扫描,需要指定路径,稍后详解
public Class MyConfig{
}

如果JavaConfig不需要自动扫描,那就需要在JavaConfig类中设置@Bean Method。示例如下:

@Configuration     // 声明这是JavaConfig,Spring会自动加载
public Class MyConfig{
@Bean(name="youSpecifiedID")
public MyType myType(){
return new MyType(); // 看这里,创建对象!!!
}
}

继续,这种情况下(不自动扫描),怎么解决依赖注入的问题?最简单的办法如下:

@Configuration
public Class MyConfig{
@Bean(name="youSpecifiedID") // 默认ID是类型首字母小写
public TypeA typeA(){
return new TypeA();
} @Bean()
public TypeB typeB(){
return new TypeB( typeA() ); // 最简单直接的办法,就是调用@Bean Method
} }

注意,上面这样直接调用@Bean Mehtod的方式,不会每次都调用@Bean Method!Spring会拦截该调用,而直接注入Bean(这里是typeA)。

JavaConfig还可以导入其他的JavaConfig或XML,如下:

@Configuration
@import( Config1.class, Config2.class ) // 导入任意多个其他的JavaConfig
@importResource( "classpath:xxx.xml" ) // 导入XML
public Class ConfigAll{
/* your Code here */
}

XML导入XML,使用<import resource="another.xml" />。

XML导入JavaConfig,使用<bean class="xx.xx.JavaConfig" />。这样Spring创建该bean的时候会自动扫描并导入相关数据。

【】【】XML配置,可以使用spring tool suite   (https://spring.io/tools/sts)
        该工具还可以检查大多数XML的配置。
    【】【】XML的依赖注入。
        【】【】构造方法:<bean ...><constructor-arg ref="refID" /></bean>        注意引用是ref,如果是字面值,使用value!!!如 value="Hello"。
                传入null:<constructor-arg><null/></constructor-arg>
        【】【】c名称空间:<bean ... c:形参名-ref="refID" />            注意,如果是字面值,使用【c:形参名】即可。形参位置也一样。
                注意,需要导入名称空间。
                形参名不方便,如果压缩文件,会破坏形参名。
                可以使用形参位置【_n】。如果只有一个形参,n可以省略。
                
        
            【】集合List和Set        
                <list>
                    <value></value>
                    <value></value>
                </list>
                <list>
                    <ref bean="refID"/>
                    <ref bean="refID"/>
                </list>
            【】property
                【】p名称空间。
                
            【】util名称空间。
                <util:constant>    References a public static field on a type
                <util:list>    java.util.List
                <util:map>    java.util.Map
                <util:properties>    java.util.Properties
                <util:property-path>    References a bean property (or nested property)
                <util:set>    java.util.Set

高级注入

不同的环境下可能需要注入不同的Bean,例如DataSource,有dev、qa和prod环境,该怎么解决?

笨办法:配置不同的XML,在编译时选择使用哪个。(例如,可以通过Maven Profiles选择。)

缺点:不同的环境需要不同的编译!!

Spring的解决方案:在运行时决定选择使用哪个。

找出需要选择的Bean,放到一个或多个Profile中,然后Spring根据不同的Profile自动选择创建的Bean。

JavaConfig中

  ① 在不自动扫描的JavaConfig中,可以使用@Profile注解到@Bean Method上

  ② 在自动扫描的JavaConfig中,需要将@Profile注解到@Component Class上

  注意:没有被@Profile的@Bean Method或@Component Class,各种环境均被创建!!!

在XML中:
       ①    <beans ... profile="dev">   
               注意,是beans,根节点。这样当前XML中的所有Bean都在dev Profile下创建。
       ②    <beans profile="dev"><bean/>...<bean/></beans>
              <beans profile="prod"><bean/>...<bean/></beans>
              注意,这里不是根节点。

Spring怎么判断Profile?

  两个地方:spring.profiles.default, spring.profiles.active

  Spring会先检查spring.profiles.active的值,有则用;没有再去检查spring.profiles.default的值,有则用,无则没有Profile。

Spring怎么去设置Profile?

       There are several ways to set these properties:
As initialization parameters on DispatcherServlet
As context parameters of a web application
As JNDI entries
As environment variables
As JVM system properties
Using the @ActiveProfiles annotation on an integration test class
例如,在web.xml中
<!-- 【】设置context的默认profile -->
<context-param>
<param-name>spring.profiles.default</param-name>
<param-value>dev</param-value>
</context-param> <!-- 【】设置servlet的默认Profile -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>spring.profiles.default</param-name>
<param-value>dev</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
上面,设置了default Profile,给dev用。其他情况下,可以通过设置active来覆盖default。

测试时,可以通过@ActiveProfiles("dev")注解到测试类上,设置并激活spring.profiles.active。

【】上面是Spring3的方式,Spring4提供了更强大的方式。
            @Conditional 注解到@Bean Method上面。

@Conditional(ConditionImpl.class)  【】这里的ConditionImpl就是Condition接口的实现类,只有一个方法,就是match,用于判断是否符合条件。

public interface Condition {
boolean matches(ConditionContext ctxt, AnnotatedTypeMetadata metadata);
}

可以通过ConditionContext实参获取Environment对象,从而判断是否包含指定的Property。

public class MagicExistsCondition implements Condition {
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment env = context.getEnvironment();
return env.containsProperty("magic"); //【】判断环境中是否包含magic Property。
}
}

只有符合的情况下,被@Conditional注解的@Bean method才会创建Bean。

【】注意,还可以通过实参(ConditionContext和AnnotatedTypeMetadata),获取其他对象,从而用于判断。
                【】Spring4,@Profile已经被重构,新版基于@Conditional实现。

【】【】解决NoUniqueBeanDefinitionException问题。
                【】【】办法一:指定primary bean。
                        @Primary 注解到@Component Class或者 @Bean Method上。
                        <bean ... primary="true"/>
                        【】注意,一种类型只能指定一个。
                        【】缺点:不能自由选择!
                【】【】办法二:@Qualifier 注解到@Autowired或者@Inject。
                            @Autowired
                            @Qualifier("iceCream")
                            public void setDessert(Dessert dessert) {
                                this.dessert = dessert;
                            }
                        【】说明,@Qualifier可以注解到@Component上,意思是将Bean的qualifier设为注解的值。如无该注解,默认类名首字母小写。
                        【】说明,@Qualifier也可以注解到@Bean Method上。相当于注解到@Component Class上。
                            因为@ComponentScan时使用@Component,没有@ComponentScan时则使用@Bean。

【】【】默认,spring中所有bean都被创建为singleton。(单例)。
                spring scope:singleton、prototype、session(web)、request(web)。
                    
                @Scope("prototype") 注解到@Component上,或<bean scope="prototype">。
                @Scope("prototype") 注解到@Bean上。
                【】SSH,应对app请求,无状态,可以考虑request scope。
                【】购物车,可以使用session scope。
                
                【】【】想知道的是,application context中,如何保证 bean id 不冲突??
                
                @Service都是单例,实际上,也是因为它都是以形参接收参数吧。且类的属性都是单例的。
                给@Service@Scope("singleton")类中的方法@Autowired注入@Scope("session")的bean时:
                    ① @Service一开始就被spring创建,而@Scope("session")则等到有请求时才会被创建,之前怎么办?
                    ② @Scope("session")的bean,应该是每个session一个,而@Service只有一个,应该怎么选择?
                【】这时,可以使用代理,让spring注入代理,然后根据实际情况选择调用的bean。这就是@Scope的属性proxyMode。
                    当proxyMode=ScopedProxyMode.INTERFACES时,只能代理接口的实现。
                    当proxyMode=ScopedProxyMode.TARGET_CLASS时,使用CGLIB,可以代理任何类。
                    
                    注解时:@Scope(value="session", proxyMode=ScopedProxyMode.TARGET_CLASS)
                    XML时: <bean ... scope="session"></bean>
                            注意,XML时,默认使用CGLIB代理,如果想使用JDK代理, <aop:scoped-proxy proxy-target-class="false" />
                            注意,XML使用proxyMode,需要导入aop空间。

【】【】【】一些值,不想硬编码,而是在运行时载入。
            Spring有两种办法:property placeholders、Spring Expression Language (SpEL)。二者类似,但用途和表现不同。
            【】【】理解什么是placeholder propery:${ xxx } 这里${} 就是placeholder,里面的xxx就是property。

            property placeholders:
该方法是从一个source加载property到Environment对象中,然后就可以使用Environment对象调用加载的property。
【】@PropertySource("classpath:/com/soundsystem/app.properties") 可以注解到JavaConfig中。
然后通过env.getProperty()即可获取需要的内容。
ƒ String getProperty(String key)
ƒ String getProperty(String key, String defaultValue) // 【】注意,可以设置默认值
ƒ T getProperty(String key, Class<T> type)
ƒ T getProperty(String key, Class<T> type, T defaultValue) // 【】注意,可以设置默认值 另外,如果要求必须提供某个property,那可以使用env.getRequiredProperty(key),这样,如果不提供,就会异常。
另外,如果想检查某个property是否存在,可以使用env.containsProperty(key)。
另外,如果想将某个property转成类对象,可以使用env.getPropertyAsClass(key,xx.class) 除了property,Environment同样提供了获取Profile的方法。
String[] getActiveProfiles()
String[] getDefaultProfiles()
boolean acceptsProfiles(String... profiles) //如果Environment支持给定的Profiles,就true。

除了Environment,还可以使用${key}的方式注入。
                
                【】【】【】使用@Value("${key}")注解。【注意与使用@Value("#{}")的区别】

                    public BlankDisc(@Value("${disc.title}") String title, @Value("${disc.artist}") String artist) {
this.title = title;
this.artist = artist;
}

使用这种方式(@Value("${key}"))时,需要配置PropertyPlaceholderConfigurer bean或PropertySourcesPlaceholderConfigurer bean。    
                从3.1开始,推荐使用PropertySourcesPlaceholderConfigurer bean。
                    在JavaConfig中配置:

                        @Bean
public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}

在XML中配置:
                        <context:property-placeholder />  注意,直接返回PropertySourcesPlaceholderConfigurer bean。

】【】Spring Expression Language (SpEL)
            The first thing to know is that SpEL expressions are framed with #{ ... }, much as property placeholders are framed with ${ ... }.
            SpEL使用#{ ... }。

                #{ 12 } 数字
#{ 9.8E4 } 98000
#{ 'abc你好' } String
#{ true }
#{ T(System).currentTimeMillis() }
【】T(System) 意思是导入java.lang.System。
#{ beanID.property }
【】根据beanID调用某个bean的属性
#{ beanID.method() }
【】根据beanID调用某个bean的method()
#{ beanID.getName().toUpperCase() }
【】这里假定beanID对应的bean有getName()方法,且返回String,那可以继续调用toUpperCase()方法。
但是,如果返回null,那就异常了!怎么解决?
解决办法:type-safe operator 【?.】
#{ beanID.getName()?.toUpperCase() } 这样,如果getName()返回null,整体就返回null。 #{jukebox.songs[4].title}
【】调用集合或数组
【】SpEL针对操作集合或数组,提供了一个选择操作符。【.?[]】
用法:#{jukebox.songs.?[artist eq 'Aerosmith']} 集合或数组中的元素的artist属性值为"Aerosmith"的,返回列表。
另外,针对操作集合或数字,还提供了【.^[]】【.?[]】 。前者是选择第一个匹配的元素,后者是选择最后一个匹配的元素。
用法:#{jukebox.songs.^[artist eq 'Aerosmith']} #{jukebox.songs.$[artist eq 'Aerosmith']}
另外,还提供了一个projection operator 【.![]】,该操作符用于投影符合的元素属性到一个新的集合。
用法:#{jukebox.songs.![title]}
【小结】
SpEL针对集合或数组的操作:
.?[] 选择所有匹配的元素(集合);
.^[] 选择第一个匹配的元素;
.$[] 选择最后一个匹配的元素。
.![] 选择属性,投影到新集合。
【】这些操作可以组合!!!就是链式编程而已。

【】【】由于都是String,所以,尽量少用 简用 SpEL!    
                                       
【】【】【】使用@Value("#{}")注入【注意与使用@Value("${key}")的区别】

public BlankDisc( @Value("#{systemProperties['disc.title']}") String title, @Value("#{systemProperties['disc.artist']}") String artist) {
this.title = title;
this.artist = artist;
}
【】【】【】XML中使用SpEL。
① <property ... value="#{}">
② <constructor-arg value="#{}">
③ p-namespace
④ c-namespace entry
【】如果想调用Class,需要使用T() operator。T()操作符主要用于调用静态方法和常量!!!
【】【】SpEL操作符的分类:
数学计算【+, -, *, /, %, ^】
比较【<, lt, >, gt, ==, eq, <=, le, >=, ge】
逻辑【and, or, not】
条件【?: (ternary 三元运算符), ?: (Elvis)】
正则【matches】 #{scoreboard.score > 1000 ? "Winner!" : "Loser"}
#{disc.title ?: 'Rattle and Hum'} 【】变种用法,如果null,则返回'Rattle and Hum'。Elvis operator。 

Spring in Action 4th 学习笔记的更多相关文章

  1. Spring in Action 4th 学习笔记 之 AOP

    前提:本文中的AOP仅限于Spring AOP. 先说说为什么需要AOP 最简单的一个例子就是日志记录,如果想记录一些方法的执行情况,最笨的办法就是修改每一个需要记录的方法.但这,真的很笨... 好的 ...

  2. spring in action 4 (学习笔记1)

    1.spring两个核心性质 DI(依赖注入) AOP(面向切面编程) 2.bean的生命周期

  3. 1、Spring In Action 4th笔记(1)

    Spring In Action 4th笔记(1) 2016-12-28 1.Spring是一个框架,致力于减轻JEE的开发,它有4个特点: 1.1 基于POJO(Plain Ordinary Jav ...

  4. Spring实战第八章学习笔记————使用Spring Web Flow

    Spring实战第八章学习笔记----使用Spring Web Flow Spring Web Flow是一个Web框架,它适用于元素按规定流程运行的程序. 其实我们可以使用任何WEB框架写流程化的应 ...

  5. 机器学习实战(Machine Learning in Action)学习笔记————09.利用PCA简化数据

    机器学习实战(Machine Learning in Action)学习笔记————09.利用PCA简化数据 关键字:PCA.主成分分析.降维作者:米仓山下时间:2018-11-15机器学习实战(Ma ...

  6. 机器学习实战(Machine Learning in Action)学习笔记————08.使用FPgrowth算法来高效发现频繁项集

    机器学习实战(Machine Learning in Action)学习笔记————08.使用FPgrowth算法来高效发现频繁项集 关键字:FPgrowth.频繁项集.条件FP树.非监督学习作者:米 ...

  7. 机器学习实战(Machine Learning in Action)学习笔记————07.使用Apriori算法进行关联分析

    机器学习实战(Machine Learning in Action)学习笔记————07.使用Apriori算法进行关联分析 关键字:Apriori.关联规则挖掘.频繁项集作者:米仓山下时间:2018 ...

  8. 机器学习实战(Machine Learning in Action)学习笔记————06.k-均值聚类算法(kMeans)学习笔记

    机器学习实战(Machine Learning in Action)学习笔记————06.k-均值聚类算法(kMeans)学习笔记 关键字:k-均值.kMeans.聚类.非监督学习作者:米仓山下时间: ...

  9. 机器学习实战(Machine Learning in Action)学习笔记————05.Logistic回归

    机器学习实战(Machine Learning in Action)学习笔记————05.Logistic回归 关键字:Logistic回归.python.源码解析.测试作者:米仓山下时间:2018- ...

随机推荐

  1. tomcat支持https的历程

    tomcat真是业界良心啊,文档写的详细无比. 一.https是什么? 简单的说,就是http+SSL/TLS 协议还是http,但是在传输层过程中使用了加密(涉及握手.秘钥分发.加密.解密等过程). ...

  2. ios app 实现热更新(无需发新版本号实现app加入新功能)

    眼下可以实现热更新的方法,总结起来有下面三种 1. 使用FaceBook 的开源框架 reactive native,使用js写原生的ios应用 ios app能够在执行时从server拉取最新的js ...

  3. hdu 4961 Boring Sum(高效)

    pid=4961" target="_blank" style="">题目链接:hdu 4961 Boring Sum 题目大意:给定ai数组; ...

  4. python 下载.whl 文件,查看已安装软件包方法

    下载地址       https://www.lfd.uci.edu/~gohlke/pythonlibs/ 另一个Python packages地址为    https://pypi.org/ 下载 ...

  5. jpa多条件查询重写Specification的toPredicate方法(转)

    Spring Data JPA支持JPA2.0的Criteria查询,相应的接口是JpaSpecificationExecutor.Criteria 查询:是一种类型安全和更面向对象的查询 . 这个接 ...

  6. Creating the Help Page in ASP.NET Web API

    Introduction In this article we will define the process of creating the help page in the ASP .NET We ...

  7. javascript淡入淡出效果的实现思路

    这个思路是最近写XScroll.js类的时候想明白的.平常我们说的淡入淡出效果,一般分成两部分,一半是淡入,另一半就是淡出了.不过经过分析,我觉得其实只需要一半就行了如题,只有思路,没有代码. 这个思 ...

  8. js操作checkbox(复选框)的方法总结

    收集了一些用js代码操作checkbox复选框的代码,分享出来,供需要的朋友参考: <script> //复选框checkbox 处理方法 //搜集整理 www.jbxue.com fun ...

  9. 【精】iOS 文件操作:沙盒(SandBox)、文件操作(FileManager)、程序包(NSBundle)

    1.沙盒机制介绍 iOS 中的沙盒机制(SandBox)是一种安全体系. 每一个 iOS 应用程序都有一个单独的文件系统(存储空间).并且仅仅能在相应的文件系统中进行操作,此区域被称为沙盒. 全部的非 ...

  10. java多线程实验 滚动字

    package com.rgy.Test; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt ...