Spring提供了三种主要的装配机制:
1. 在XML中进行显示的装配2. 在Java中进行显示的配置
3. 隐式的bean发现机制和自动装配
下面看第一种,在XML中进行显示的装配
通过XML显式的装配Bean
概述:
一、手动配置Bean XML方式
二、构造器注入Bean引用
三、构造器注入Bean引用(属性字段)
四、构造器注入Bean引用(字面量注入到构造器中)
五、构造器注入Bean引用(装配集合)
六、手动配置Bean XML方式(引入外部配置)
七、手动配置Bean XML方式(引入多个外部配置)
一、手动配置Bean XML方式
代码优先
package com.test.spring.server.inter;
/**
* 人员信息
*
* @author CYX
* @create 2018-04-14-14:18
*/
public interface People {
void sayName();
}
package com.test.spring.server.test1;
import com.test.spring.server.inter.People;
/**
* @author CYX
* @create 2018-04-16-7:10
*/
public class CYXPeople implements People {
private String name;
public void setName(String name) {
this.name = name;
}
@Override
public void sayName() {
System.out.println("my name : " + name);
}
}
applicationContext.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"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<bean id="cyxPeople" class="com.test.spring.server.test1.CYXPeople">
<property name="name" value="CYX"></property>
</bean>
</beans>
主方法
package com.test.spring.server.test1;
import com.test.spring.server.inter.People;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Hello world!
*/
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring/test1/applicationContext.xml");
People propleBean = (People) context.getBean("cyxPeople");
propleBean.sayName();
}
}
输出结果:
从上面applicationContext.xml配置文件中,可以看到其中配置了<bean></bean>标签。
<beans></beans> 元素是Spring配置文件的根元素。
<bean></bean>元素是<beans></beans>元素的子元素。
<beans></beans> 元素可以包含多个<bean></bean>元素。
每个<bean>元素可以定义一个Bean实例,每一个Bean对应Spring容器中的一个Java实例。
定义Bean时通常需要指定两个元素:
id | 确定该bean(java实例)的唯一标识,容器对bean管理、访问以及该bean依赖关系,都是通过该属性完成。 bean的id在Spring容器中是唯一的! |
class | 指定该bean的具体实现类。注意这里不能使用接口。通常情况下,Spring会直接使用new关键字创建该bean的实例,因此,这里必须提供bean实现类的全类名。 |
当Spring发现<bean>元素时,它将会调用 实例对象(com.test.spring.server.test1.CYXPeople)的默认构造器来创建bean。
在Spring XML配置中,只有一种声明bean的方式:使用<bean>元素并指定class属性。Spring会从这里获取必要的信息来创建bean。
二、构造器注入Bean引用
代码优先,上面的代码稍微修改一下
package com.test.spring.server.inter;
/**
* 人员信息
*
* @author CYX
* @create 2018-04-14-14:18
*/
public interface People {
void sayName();
void spellCheck();
}
package com.test.spring.server.test1;
/**
* @author CYX
* @create 2018-04-30-8:34
*/
public class SpellChecker {
public SpellChecker() {
System.out.println("SpellChecker 初始化");
}
public void checkSpelling() {
System.out.println("执行checkSpelling方法.");
}
}
package com.test.spring.server.test1;
import com.test.spring.server.inter.People;
/**
* @author CYX
* @create 2018-04-16-7:10
*/
public class CYXPeople implements People {
private String name;
private SpellChecker spellChecker;
public CYXPeople() {
}
public CYXPeople(SpellChecker spellChecker) {
System.out.println("CYXPeople构造器 注入SpellChecker");
this.spellChecker = spellChecker;
}
@Override
public void spellCheck() {
spellChecker.checkSpelling();
}
public void setName(String name) {
this.name = name;
}
@Override
public void sayName() {
System.out.println("my name : " + name);
}
}
applicationContext.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"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<bean id="cyxPeople" class="com.test.spring.server.test1.CYXPeople">
<property name="name" value="CYX"></property>
<constructor-arg ref="spellChecker"/>
</bean>
<bean id="spellChecker" class="com.test.spring.server.test1.SpellChecker">
</bean>
</beans>
主方法
package com.test.spring.server.test1;
import com.test.spring.server.inter.People;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Hello world!
*/
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring/test1/applicationContext.xml");
People propleBean = (People) context.getBean("cyxPeople");
propleBean.sayName();
propleBean.spellCheck();
}
}
输出结果:
按照上面的代码,CYXPeople Bean 有一个接受 spellChecker 类型的构造器。
看下配置:
<bean id="cyxPeople" class="com.test.spring.server.test1.CYXPeople">
<property name="name" value="CYX"></property>
<constructor-arg ref="spellChecker"/>
</bean>
当Spring遇到这个<bean>元素时,它会创建一个cyxPeople实例。
<constructor-arg>元素会告知Spring要将一个 id 为 spellChecker 的 bean引用传递到 CYXPeople 的构造器中。
三、构造器注入Bean引用(属性字段)
代码优先
package com.test.spring.server.inter;
/**
* 人员信息
*
* @author CYX
* @create 2018-04-14-14:18
*/
public interface People {
void sayName();
void spellCheck();
}
package com.test.spring.server.test1;
/**
* @author CYX
* @create 2018-04-30-8:34
*/
public class SpellChecker {
private String name;
private String address;
public SpellChecker(String name, String address) {
this.name = name;
this.address = address;
}
public SpellChecker() {
System.out.println("SpellChecker 初始化");
}
public void checkSpelling() {
System.out.println("执行checkSpelling方法.");
System.out.println("name : " + name + " , address : " + address);
}
public void setName(String name) {
this.name = name;
}
public void setAddress(String address) {
this.address = address;
}
}
package com.test.spring.server.test1;
import com.test.spring.server.inter.People;
/**
* @author CYX
* @create 2018-04-16-7:10
*/
public class CYXPeople implements People {
private String name;
private SpellChecker spellChecker;
public CYXPeople() {
}
public CYXPeople(SpellChecker spellChecker) {
System.out.println("CYXPeople构造器 注入SpellChecker");
this.spellChecker = spellChecker;
}
@Override
public void spellCheck() {
spellChecker.checkSpelling();
}
public void setName(String name) {
this.name = name;
}
@Override
public void sayName() {
System.out.println("my name : " + name);
}
}
applicationContext.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"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<bean id="cyxPeople" class="com.test.spring.server.test1.CYXPeople">
<property name="name" value="CYX"></property>
<constructor-arg ref="spellChecker"/>
</bean>
<bean id="spellChecker" class="com.test.spring.server.test1.SpellChecker">
<!--字段属性注入-->
<property name="name" value="CYX9999"></property>
<property name="address" value="CYX9999"></property>
</bean>
</beans>
主方法
package com.test.spring.server.test1;
import com.test.spring.server.inter.People;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Hello world!
*/
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring/test1/applicationContext.xml");
People propleBean = (People) context.getBean("cyxPeople");
propleBean.sayName();
propleBean.spellCheck();
}
}
输出结果:
可以看到 构造器注入bean 引用的时候,将字段也注入进去了。
依靠 SpellChecker 中字段的setter方法。
<property>元素为属性的setter方法所提供的功能与<constructor-arg>元素为构造器所提供的的功能是一样的。
四、构造器注入Bean引用(字面量注入到构造器中)
代码优先,沿用上面的主要代码,修改如下:
package com.test.spring.server.test1;
/**
* @author CYX
* @create 2018-04-30-8:34
*/
public class SpellChecker {
private String name;
private String address;
public SpellChecker(String name, String address) {
this.name = name;
this.address = address;
}
public SpellChecker() {
System.out.println("SpellChecker 初始化");
}
public void checkSpelling() {
System.out.println("执行checkSpelling方法.");
System.out.println("name : " + name + " , address : " + address);
}
}
<?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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<bean id="cyxPeople" class="com.test.spring.server.test1.CYXPeople">
<property name="name" value="CYX"></property>
<constructor-arg ref="spellChecker"/>
</bean>
<bean id="spellChecker" class="com.test.spring.server.test1.SpellChecker">
<!--构造器 字段属性注入-->
<constructor-arg value="cyx000"/>
<constructor-arg value="北京"/>
</bean>
</beans>
其他代码不变
输出结果:
对比下代码发现,SpellChecker中字段属性的 setter 的方法没有了。
applicationContext.xml 中 元素节点也变了。
五、构造器注入Bean引用(装配集合)
代码优先
package com.test.spring.server.inter;
/**
* 人员信息
*
* @author CYX
* @create 2018-04-14-14:18
*/
public interface People {
void sayName();
void spellCheck();
}
package com.test.spring.server.test1;
import java.util.List;
/**
* @author CYX
* @create 2018-04-30-8:34
*/
public class SpellChecker {
private String name;
private String address;
private List<String> infos;
public SpellChecker(String name, String address, List<String> infos) {
this.name = name;
this.address = address;
this.infos = infos;
}
public SpellChecker(String name, String address) {
this.name = name;
this.address = address;
}
public SpellChecker() {
System.out.println("SpellChecker 初始化");
}
public void checkSpelling() {
System.out.println("执行checkSpelling方法.");
System.out.println("name : " + name + " , address : " + address);
System.out.println("infos : " + infos);
}
}
package com.test.spring.server.test1;
import com.test.spring.server.inter.People;
/**
* @author CYX
* @create 2018-04-16-7:10
*/
public class CYXPeople implements People {
private String name;
private SpellChecker spellChecker;
public CYXPeople() {
}
public CYXPeople(SpellChecker spellChecker) {
System.out.println("CYXPeople构造器 注入SpellChecker");
this.spellChecker = spellChecker;
}
@Override
public void spellCheck() {
spellChecker.checkSpelling();
}
public void setName(String name) {
this.name = name;
}
@Override
public void sayName() {
System.out.println("my name : " + name);
}
}
applicationContext.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"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<bean id="cyxPeople" class="com.test.spring.server.test1.CYXPeople">
<property name="name" value="CYX"></property>
<constructor-arg ref="spellChecker"/>
</bean>
<bean id="spellChecker" class="com.test.spring.server.test1.SpellChecker">
<!--构造器 字段属性注入-->
<constructor-arg index="0" value="cyx000"/>
<constructor-arg index="1" value="北京"/>
<constructor-arg index="2">
<list>
<value>123</value>
<value>456</value>
<value>789</value>
<value>098</value>
<value>765</value>
<value>4321</value>
</list>
</constructor-arg>
</bean>
</beans>
主方法
package com.test.spring.server.test1;
import com.test.spring.server.inter.People;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Hello world!
*/
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring/test1/applicationContext.xml");
People propleBean = (People) context.getBean("cyxPeople");
propleBean.sayName();
propleBean.spellCheck();
}
}
输出结果:
<list>元素是<constructor-arg>的子元素,这表明一个包含值的列表将会传递到构造器中。
其中<value>元素用来指定列表中的每个元素。与之类似,你也可以用<ref> 转配bean。
六、手动配置Bean XML方式(引入外部配置)
代码优先
package com.test.spring.server.inter;
/**
* 人员信息
*
* @author CYX
* @create 2018-04-14-14:18
*/
public interface People {
void sayName();
}
package com.test.spring.server.test2;
import com.test.spring.server.inter.People;
/**
* @author CYX
* @create 2018-04-16-22:24
*/
public class OnePeople implements People {
private String name;
private String age;
private String address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public void sayName() {
System.out.println("OnePeople{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
", address='" + address + '\'' +
'}');
}
}
test2.properties
test2.name=cyx222
test2.age=25
test2.address=南京
applicationContext.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"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<!--定义一个对象,通过占位符从配置文件中读取配置-->
<bean id="onePeople" class="com.test.spring.server.test2.OnePeople">
<property name="name">
<value>${test2.name}</value>
</property>
<property name="age">
<value>${test2.age}</value>
</property>
<property name="address">
<value>${test2.address}</value>
</property>
</bean>
<!--指定外部properties配置文件-->
<bean id="propertiesConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:spring/test2/test2.properties</value>
</list>
</property>
</bean>
</beans>
主方法
package com.test.spring.server.test2;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Spring读取properties配置文件,占位符指向的配置信息放在bean中定义的工具
*
* @author CYX
* @create 2018-04-16-22:23
*/
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring/test2/applicationContext.xml");
OnePeople onePeople = context.getBean("onePeople", OnePeople.class);
onePeople.sayName();
}
}
输出结果:
从上面的配置文件可以看出,配置文件中的参数已经被引用到了bean的配置中。
在applicationContext.xml中有一个配置:
org.springframework.beans.factory.config.PropertyPlaceholderConfigurer
PropertyPlaceholderConfigurer类是用来解析Java properties属性文件的,并提供在Spring配置期间替换使用属性值。
PropertyPlaceholderConfigurer是beanFactory工厂后置处理器的实现,也就是BeanFactoryPostProcessor接口的一个实现。
PropertyPlaceholderConfigurer可以将上下文(配置文件)种的属性值放在另一个单独的Java properties文件中去。
在XML文件中使用 ${key} 替换指定的properties的值。这样的话,只需要对properties文件进行修改,而不用对xml配置文件进行修改。
七、手动配置Bean XML方式(引入多个外部配置)
代码优先
test3.properties
test3.name=cyx333
test3.age=25
test3.address=南京
test3-1.properties
test.name=cyx-31
test.age=25-31
test.address=南京-31
CustomizedPropertyConfigurer自定义读取配置类
package com.test.spring.server.test3;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/**
* @author CYX
* @create 2018-04-16-22:40
*/
public class CustomizedPropertyConfigurer extends PropertyPlaceholderConfigurer {
private static Map<String, String> ctxPropMap;
@Override
protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props) throws BeansException {
super.processProperties(beanFactoryToProcess, props);
ctxPropMap = new HashMap<String, String>();
for (Object key : props.keySet()) {
String keyStr = key.toString();
String valueStr = String.valueOf(props.getProperty(keyStr));
ctxPropMap.put(keyStr, valueStr);
}
}
public static String getCtxPro(String name) {
return ctxPropMap.get(name);
}
public static Map<String, String> getCtxPropMap() {
return ctxPropMap;
}
}
applicationContext.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"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<!--指定外部properties配置文件-->
<bean id="customizedPropertyConfigurer" class="com.test.spring.server.test3.CustomizedPropertyConfigurer">
<property name="locations">
<list>
<value>classpath:spring/test3/test3.properties</value>
<value>classpath:spring/test3/test3-1.properties</value>
</list>
</property>
<property name="fileEncoding" value="utf-8"/>
</bean>
</beans>
主方法
package com.test.spring.server.test3;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Spring加载properties,获取指定key的value
*
* @author CYX
* @create 2018-04-16-22:39
*/
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring/test3/applicationContext.xml");
System.out.println(CustomizedPropertyConfigurer.getCtxPro("test3.name"));
System.out.println(CustomizedPropertyConfigurer.getCtxPro("test3.age"));
System.out.println(CustomizedPropertyConfigurer.getCtxPro("test3.address"));
System.out.println(CustomizedPropertyConfigurer.getCtxPro("test.name"));
System.out.println(CustomizedPropertyConfigurer.getCtxPro("test.age"));
System.out.println(CustomizedPropertyConfigurer.getCtxPro("test.address"));
}
}
输出结果:
参考文章:
http://wiki.jikexueyuan.com/project/spring/bean-definition.html
https://blog.csdn.net/chenssy/article/details/8222744
http://bijian1013.iteye.com/blog/2256728
https://blog.csdn.net/qq_35893120/article/details/79159965
https://www.cnblogs.com/xlchen/p/5947641.html
《Spring 实战》