Spring
0.测试
对于组件扫描的测试
package soundsystem ;
import static org. junit. Assert . *;
import org. junit. Test ;
import org. junit. runner. RunWith ;
import org. springframework. beans. factory. annotation. Autowired ;
import org. springframework. test. context. ContextConfiguration ;
import org. springframework. test. context. junit4. SpringJUnit4ClassRunner ;
@RunWith ( SpringJUnit4ClassRunner . class )
@ContextConfiguration ( classes = CDPlayerConfig . class )
public class CDPlayerTest {
@Autowired
private CompactDisc cd;
@Test
public void cdShouldNotBeNull ( ) {
assertNotNull ( cd) ;
}
}
1.Bean的装配
可选方法
自动化装配
使用@Component来标识这个类是一个Bean 可以使用@Component(“Bean’s Name”) 来显式的指定这个Bean的id,如果我们不进行显式的指定,比如这个类叫 Ice 那么它的id默认为 ice(也就是类名的第一个字母变为小写)
com. cheng. pojo
@Component ( "ICEEEEEE" )
public class Ice {
private Double temperature;
public bool cold ( ) {
if ( temperature < - 10 )
return true ;
return false ;
}
}
使用@ComponentScan来告诉Spring应该在哪些地方进行扫描(即Bean应该在哪找) 如果不给他设置任何属性,它会默认以配置类所在的包作为基础包来扫描组件
com. cheng. config
@Configuration
@ComponentScan
public class WeatherConfig {
}
<?xml version="1.0" encoding="UTF-8"?>
< beans xmlns = " http://www.springframework.org/schema/beans"
xmlns: xsi= " http://www.w3.org/2001/XMLSchema-instance"
xmlns: context= " http://www.springframework.org/schema/context"
xsi: schemaLocation= "
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd" >
< context: component-scan base-package = " soundsystem" />
</ beans>
给@ComponentScan设置基础包
@ComponentScan ( "pojo" )
@ComponentScan ( basePackages= "pojo" )
@ComponentScan ( basePackageClasses= { Ice . class , LoginServlet . class } )
使用@Autowired注解实现自动装配(该注解不仅可以使用在类的构造器和Sette方法上,实际上,它可以用在类的任何方法上,只要这个方法需要一个Bean)
@Component
public class CDPlayer implements MediaPlayer {
private CompactDisc cd;
@Autowired
public CDPlayer ( CompactDisc cd) {
this . cd = cd;
}
@Autowired
public void setCompactDisc ( CompactDisc cd) {
this . cd = cd;
}
}
标记有@Autowired的方法,Spring都会尝试满足方法参数上所声明的依赖,加入有且只有一个Bean匹配依赖需求的话,那么这个Bean将会被装配进来,但是要注意,Spring默认情况下是单例的 如果没有匹配的Bean,那么在Spring的应用上下文创还能得时候,Spring将会抛出一个异常,如果我们允许不强制需要Bean来注入,可以将@Autowired的require属性设置为false
XML装配
创建XML配置规范
最为简单的SpringXML配置如下所示
<?xml version="1.0" encoding="UTF-8"?>
< beans xmlns = " http://www.springframework.org/schema/beans"
xmlns: xsi= " http://www.w3.org/2001/XMLSchema-instance"
xsi: schemaLocation= " http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context" >
</ beans>
声明一个简单的bean
< bean class = " soundsystem.SgtPeppers" />
借助构造器注入初始化bean
使用<constructor-arg>元素
使用c-命名空间
将对象的引用装配到依赖于它们的其他对象之中
首先,要使用c-命名空间,需要在XML的顶部声明其模式,如下所示
<?xml version="1.0" encoding="UTF-8"?>
< beans xmlns = " http://www.springframework.org/schema/beans"
xmlns: c= " http://www.springframework.org/schema/c"
xmlns: xsi= " http://www.w3.org/2001/XMLSchema-instance"
xsi: schemaLocation= " http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd" >
</ beans>
在c-命名空间和模式声明之后,我们就可以使用它来声明构造器参数了,如下所示
< bean id = " cdPlayer" class = " soundsystem.CDPlayer"
c: cd-ref= " compactDisc" />
c-命名空间前缀 构造器参数名 注入bean引用 要注入的bean的ID
c : cd - ref = "compactDisc"
将字面量注入到构造器中
c-命名空间无法将集合装配到构造器参数中 借助Setter方法实现属性注入
JAVA装配
使用JavaConfig显式装配Spring
创建JavaConfig类的关键在于为其添加@Configuration注解,这个注解表明这个类是一个配置类
因为这节我们关注于显式配置,因此我们移除@ComponentScan注解,但要注意,自动化配置和XMl配置和Java配置是可以共存的。
显式声明Bean
借助JavaConfig实现注入
引用创建Bean的方法
@Bean
public CDPlayer cdPlayer ( ) {
return new CDPlayer ( sgtPeppers ( ) ) ;
}
这个Bean和sgtPeppers稍微有些区别,在这里并没有使用默认的构造器来构建实例,而是调用了需要传入CompactDisc对象的构造器来创建CDPlayer实例 看起来,CompactDisc是通过调用sgtPeppers()得到的,但情况并非完全如此,因为sgtPeppers()方法上添加了@Bean注解,Spring将会拦截所有对它的调用,并确保直接返回该方法所创建的Bean,而不是每次都对其进行实际的调用、 而且Spring默认是单例模式,也就是每一个cdPlayer获得的CD光盘都是完全一样的。 这种形式还有另一种理解起来比较简单的方式 JAVA @Bean
public CDPlayer cdPlayer ( CompactDisc compactDisc) {
return new CDPlayer ( compactDisc) ;
}
依赖于这种方式,你可以将配置分散到多个配置类,XML,以及自动扫描和装配Bean中,不管CompactDisc是采用什么方式创建出来的,只要Spring中托管的Bean可以返回一个CompactDisc,它就可以将它提供给需要它的Bean 当然,你也可以使用Setter风格的DI配置 JAVA @Bean
public CDPlayer cdPlayer ( CompactDisc compactDisc) {
CDPlayer cdPlayer = new CDPlayer ( compactDisc) ;
cdPlayer. setCompactDisc ( compactDisc) ;
return cdPlayer;
}
最重要的是,带有@Bean注解的方法可以采用任何必要的Java功能来产生bean实例,这里所存在的可能性仅仅受到Java语言的限制
导入和混合配置
1.在JavaConfig中引用XML配置
假设我们现在有三个JavaConfig配置类
@Configuration
public class CDConfig {
@Bean
public CompactDisc compactDisc ( ) {
return new SgtPeppers ( ) ;
}
}
@Configuration
public class CDPlayerConfig {
@Bean
public CDPlayer cdPlayer ( CompactDisc compactDisc) {
return new CDPlayer ( compactDisc) ;
}
}
@Configuration
@Import ( { CDPlayerConfig . class , CDConfig . class } )
public class SoundSystemConfig {
}
2.在XML配置中引用JavaConfig
2.高级装配
Spring profile
如果要在不同的环境(dev,prod,test)中配置使用不同的Bean,可以配置Spring profile
声明Bean所在的环境,只需使用@Profile注解,或者通过<beans>的profile属性。
@Configuration
public class DataSourceConfig {
@Bean
@Profile ( "dev" )
public DataSource devDataSource ( ) {
return devxxx;
}
@Bean
@Profile ( "prod" )
public DataSource prodDataSource ( ) {
return prodxxx;
}
}
尽管这两个Bean都被声明在一个profile中,但是只有规定的profile激活时,响应的bean才会被创建 没有指定profile的Bean始终都会被创建,与激活哪个profile没有关系 XML <?xml version="1.0" encoding="UTF-8"?>
< beans xmlns = " http://www.springframework.org/schema/beans"
xmlns: xsi= " http://www.w3.org/2001/XMLSchema-instance"
xmlns: context= " http://www.springframework.org/schema/context"
xsi: schemaLocation= "
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"
profile = " dev" >
</ beans>
那么,如何激活某个profile呢?
关键有两个属性:spring.profiles.active 和 spring.profiles.default
有多种方式来设置这两个属性
作为DispatcherServlet的初始化参数 作为Web应用的上下文参数
<?xml version="1.0" encoding="UTF-8"?>
< web-app version = " 2.5"
xmlns = " http://java.sun.com/xml/ns/javaee"
xmlns: xsi= " http://www.w3.org/2001/XMLSchema-instance"
xsi: schemaLocation= " http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" >
< context-param>
< param-name> contextConfigLocation</ param-name>
< param-value> /WEB-INF/spring/root-context.xml</ param-value>
</ context-param>
< context-param>
< param-name> spring.profiles.default</ param-name>
< param-value> dev</ param-value>
</ context-param>
< listener>
< listener-class> org.springframework.web.context.ContextLoaderListener</ listener-class>
</ listener>
< 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>
< servlet-mapping>
< servlet-name> appServlet</ servlet-name>
< url-pattern> /</ url-pattern>
</ servlet-mapping>
</ web-app>
作为环境变量 作为JVM的系统属性 在集成测试类上,使用@ActiveProfiles注解设置
@RunWith ( SpringJUnit4ClassRunner . class )
@ContextConfiguration ( classes= { PresistenceTestConfig . class } )
@ActiveProfiles ( "dev" )
public class PersistenceTest {
. . .
}
在条件化创建Bean方面,profile机制通过基于哪个profile处于激活状态来判断,而Spring4.0提供了一种更为通用的机制来实现条件化的Bean定义 这就是使用@Conditional注解定义条件化的bean
条件化的bean声明
可以给一个类设置@Conditional注解,注解中只需给定一个实现类Condition接口的类,@Conditional注解会自动调取Condition接口进行条件对比
@Bean
@Conditional ( MagicExistsCondition . class )
public MagicBean magicBean ( ) {
return new MagicBean ( ) ;
}
public interface Condition {
boolean matches ( ConditionContext ctxt, AnnotatedTypeMetadata metadata) ;
}
JAVA: MagicExistsCondition类 public class MagicExistsCondition implements Condition {
public boolean matches ( ConditionContext ctxt, AnnotatedTypeMetadata metadata) {
Environment env = context. getEnvironment ( ) ;
return env. containsProperty ( "magic" ) ;
}
}
public interface ConditionContext {
BeanDefinitionRegistry getRegistry ( ) ;
ConfigurableListableBeanFactory getBeanFactory ( ) ;
Environment getEnvironment ( ) ;
ResourceLoader getResourceLoader ( ) ;
ClassLoader getClassLoader ( ) ;
}
AnnotatedTypeMetadata接口则能够让我们检查带有@Bean注解的方法上还有什么其他的注解。
自动装配的歧义性
bean的作用域
Spring表达式语言