1.spring配置可选方案
在spring中,对象无需自己查找或创建其所关联的其他对象。相反,容器负责把需要相互协作的对象引用赋予各个对象。
创建对象之间的协作关系的行为通常称为装配,这也是依赖注入的本质。spring提供了3中主要的装配机制(可相互搭配):
- 在XML里面进行显示的配置
- 在Java中进行显示的配置
- 隐式的bean发现机制和自动装配
建议顺序为 3>2>1
2.自动化装配bean
spring从两个角度来实现自动化装配:
- 组件扫描(component scanning):spring会自动发现应用上下文中所发现的bean
- 自动装配(autowiring):spring自动满足bean之间的依赖
组件扫描和自动装配组合在一起能够将你的显示配置降低到最少
package c2_wirebean;
// CompactDisc 接口在 java 中定义了 CD 的概念
public interface CompactDisc {
void play();
}
package c2_wirebean;
import org.springframework.stereotype.Component;
// 带有 @Component 注解的 CompactDisc 实现类 Sgtpeppers
@Component("compactDisc")
public class Sgtpeppers implements CompactDisc {
private String title = "Sgtpeppers loney heart club band";
private String artist = "the beatles";
@Override
public void play() {
System.out.println("playing " + title + " by " + artist);
}
}
第一种:使用java配置类
package c2_wirebean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
// 定义配置类
@Configuration
// 定义扫描包,默认扫描与该类相同的包
@ComponentScan(basePackages = {"c2_wirebean"})
public class CDPlayerConfig {
}
package c2_wirebean;
// 静态导包
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);
cd.play();
}
}
第二种:使用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-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<!-- 配置扫描包 -->
<context:component-scan base-package="c2_wirebean"/>
</beans>
package c2_wirebean;
// 静态导包
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(value = {"/CDPlayerConfig.xml"})
public class CDPlayerTest2 {
@Autowired
private CompactDisc cd;
@Test
public void cdShouldNotBeNull() {
assertNotNull(cd);
cd.play();
}
}
3.使用java代码配置bean
package c2_wirebean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
// 定义配置类
@Configuration
// 定义扫描包,默认扫描与该类相同的包
@ComponentScan(basePackages = {"c2_wirebean"})
public class CDPlayerConfig {
@Bean(name="compactDisc") //可通过name指定bean的名称
public CompactDisc sgtpeppers() {
return new Sgtpeppers();
}
}
我们在 sgtpeppers() 方法上添加了 @Bean 注解,在我们要使用 CompactDisc 对象的时候,spring会拦截所有对他的调用,并确保直接返回该方法所创建的bean,而不是每次都对他进行调用,因为spring创建的bean默认是单例的(singleton)。
4.使用XML配置bean
<?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-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<!-- 配置扫描包 -->
<!-- <context:component-scan base-package="c2_wirebean"/> -->
<bean id="compactDisc" class="c2_wirebean.Sgtpeppers"/>
</beans>
5.通过XML装配bean
package c2_wirebean;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
public class Student {
private String name;
private Integer age;
private List<String> course;
public Student() {}
public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", course=" +
StringUtils.join(course.stream().map(String::toUpperCase).collect(Collectors.joining(",", "{", "}")), "") + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public List<String> getCourse() {
return course;
}
public void setCourse(List<String> course) {
this.course = course;
}
}
<?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"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<!-- 配置扫描包 -->
<!-- <context:component-scan base-package="c2_wirebean"/> -->
<!-- <bean id="compactDisc" class="c2_wirebean.Sgtpeppers"/> -->
<!-- 使用 constructor-arg 进行构造器参数的注入 -->
<!-- <bean id="student" class="c2_wirebean.Student">
<constructor-arg value="zhangsan"/>
<constructor-arg value="18"/>
</bean> -->
<!-- 使用 c 命名空间注入 -->
<!-- <bean id="student" class="c2_wirebean.Student"
c:_title="zhangsan" c:_age="18"/> -->
<!-- <bean id="student" class="c2_wirebean.Student"
c:_0="zhangsan" c:_1="18"/> -->
<!-- 使用 p 命名空间注入 -->
<!-- <bean id="student" class="c2_wirebean.Student"
p:name="zhangsan" p:age="18"/> -->
<!-- 在 Student 类中添加一个课程的list属性-->
<!-- <bean id="student" class="c2_wirebean.Student" p:name="zhangsan" p:age="18">
<property name="course">
<list>
<value>Chinese</value>
<value>Math</value>
<value>English</value>
</list>
</property>
</bean> -->
<!-- 注:list和set区别不大,最重要的不同在于当Spring在创建要装配的集合时,所创建的是java.util.List还是java.util.Set
如果是 Set的话,所有重复值会被忽略掉,存放顺序也没有保障-->
<!-- 使用util:list -->
<bean id="student" class="c2_wirebean.Student" p:name="zhangsan" p:age="18" p:course-ref="course"/>
<util:list id="course">
<value>Chinese</value>
<value>Math</value>
<value>English</value>
</util:list>
</beans>
输出: