Spring框架作为Bean的管理容器,其最经典最基础的Bean配置方式就是纯XML配置,这样做使得结构清晰明了,适合大型项目使用。Spring的XML配置虽然很繁琐,而且存在简洁的注解方式,但读懂XML配置文件对我们来说依然很重要,尚且对于老系统维护必不可少的面对XML配置。
下面通过案例来理解XML配置。
案例:(一个基础的Bean)
public class Pet { private String petType; private String color ; public String getColor() { return color; } public void setColor(String color) { this.color = color; } public String getPetType() { return petType; } public void setPetType(String petType) { this.petType = petType; } public String toString(){ return"petType: "+petType+" color: "+color; } }
public class User { String id; String name; String passWord; Pet pet; public Pet getPet() { return pet; } public void setPet(Pet pet) { this.pet = pet; } public User(){ System.out.println("spring 需要一个空参构造!"); } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassWord() { return passWord; } public void setPassWord(String passWord) { this.passWord = passWord; } @Override public String toString() { return "User{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", passWord='" + passWord + '\'' + ", pet=" + pet + '}'; } public void init(){ System.out.println("User初始化执行init方法!"); } public void userDestroy(){ System.out.println("userDestroy方法被执行!"); } }
import com.bing.tao.bean.User; import org.junit.jupiter.api.Test; import org.springframework.context.support.ClassPathXmlApplicationContext; public class HelloSpring { /** * IOC的反转:创建对象这份工作由我们自己执行反转给spring帮我们执行; * IOC的控制:就是由spring帮我们负责创建销毁对象,掌控对象的生命周期等,我们在需要使用对象的时候跟Spring申请即可; * IOC是一种编程思想,也是一种新的设计模式,它需要DI(依赖注入)技术的支持; * spring是一个容器,它将帮我们管理对象 */ @Test public void Test1(){ //根据spring配置文件获取容器对象 //ApplicationContext 配置的所有bean都会在容器创建的时候被创建出来 //如果配置的bean较多,那么在创建容的时候,会产生内存过大的问题;这种情况在机器硬件性能较为落后的时候体现的比较明显; //延迟加载 true就是创建容器时不加载配置的bean对象,在获取的时候才创建; ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); User user= (User) applicationContext.getBean("user"); System.out.println("user: "+user); //通过getBean获取配置好的user对象(程序员向spring容器要对象) user= applicationContext.getBean(User.class); System.out.println("user: "+user); applicationContext.close(); } }
重要的配置:(创建一个名字叫: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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- spring管理bean的XML,一个bean标签表示一个bean。--> <!-- name属性给bean取名,代码中可以通过:applicationContext.getBean("user"); 获取class--> <!-- class:是被管理对象的全包名,spring会通过这个包名来创建对象 --> <!-- scope 属性,控制对象的单例还是多例,prototype多例--> <!-- 在web环境下,如果scope属性为request 那么这个对象被创建出来 他的生命周期会与request请求一致--> <!-- session 同理 ,生命周期与session一致 --> <!-- lazy-init 延迟加载,获取bean 的时候才加载 ,否则在创建容器是就会加载bean。--> <!-- 初始化方法:init-method,spring创建bean的时候会执行--> <!-- 销毁bean方法:destroy-method spring销毁bean的时候会执行--> <bean name = "user" class="com.bing.tao.bean.User" scope="singleton" lazy-init="false" init-method="init" destroy-method="userDestroy"> <!-- property 标签,是用于bean内部属性初始化值使用的。--> <!-- name 对应bean的变量名,value 就是初始值。--> <property name="id" value="1"></property> <property name="name" value="蕾蕾"></property> <property name="passWord" value="123456"></property> <!-- 引用类型的初始化 --> <property name="pet" ref="pet"></property> </bean> <!-- 将pet对象交给spring管理,并注入值类型 --> <bean name = "pet" class="com.bing.tao.bean.Pet"> <property name="petType" value="二哈"></property> <property name="color" value="灰灰"></property> </bean> </beans>
运行结果:
配置文件,已经将标签含义说明清楚。补充一点:如果是多例则spring不在管理bean而是交给你管理,销毁方法将不再执行。
Spring XML配置如何支持构造函数和复杂数据类型(List等):
修改User类:
public class User { String id; String name; String passWord; Pet pet; public Pet getPet() { return pet; } public void setPet(Pet pet) { this.pet = pet; } public User(){ System.out.println("spring 需要一个空参构造!"); } public User(String name, Pet pet) { System.out.println("打印构造方法1:name :"+name +"pet:"+pet); this.name = name; this.pet = pet; } public User(Pet pet,String name) { System.out.println("打印构造方法2:name :"+name +"pet:"+pet); this.name = name; this.pet = pet; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassWord() { return passWord; } public void setPassWord(String passWord) { this.passWord = passWord; } @Override public String toString() { return "User{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", passWord='" + passWord + '\'' + ", pet=" + pet + '}'; } public void init(){ System.out.println("User初始化执行init方法!"); } public void userDestroy(){ System.out.println("userDestroy方法被执行!"); } }
新增测试方法:
import com.bing.tao.bean.MyCollection; import com.bing.tao.bean.User; import org.junit.jupiter.api.Test; import org.springframework.context.support.ClassPathXmlApplicationContext; public class HelloSpring2 { @Test public void Test1(){ ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext_Injection.xml"); User user= (User) applicationContext.getBean("user"); System.out.println(user); System.out.println("-----------------分割线-----------------"); MyCollection myCollection= (MyCollection) applicationContext.getBean("myCollection"); System.out.println(myCollection); } }
新增配置文件:applicationContext_Injection.xml
配置内容如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 构造方法注入 --> <bean name="user" class="com.bing.tao.bean.User"> <!-- name 调用构造方法的参数名称 value 是注入值类型 ref 注入引用类型 --> <!-- type 是指定参数的类型 --> <!-- index 是指定参数的 --> <constructor-arg name="name" value="老王" type="java.lang.String" index="1"/> <constructor-arg name="pet" ref="pet"/> </bean> <!-- 将pet对象交给spring管理,并注入值类型 --> <bean name = "pet" class="com.bing.tao.bean.Pet"> <property name="petType" value="二哈"></property> <property name="color" value="灰灰"></property> </bean> <!-- 复杂类型注入 --> <bean name="myCollection" class="com.bing.tao.bean.MyCollection"> <!-- Array --> <property name="array"> <array> <value>123</value> <value>abc</value> <ref bean="pet"></ref> </array> </property> <!-- List --> <property name="list"> <list> <value>456</value> <value>def</value> <ref bean="user"></ref> </list> </property> <!-- Set --> <!-- 当只有一个值得时候,可以简写成一下方式。 --> <property name="set" value="789"></property> <!-- Map --> <property name="map"> <map> <entry key="root" value="123"></entry> <entry key="admin" value="456"></entry> <entry key-ref="user" value-ref="pet"></entry> </map> </property> <!-- properties --> <property name="prop"> <props> <prop key="name">老李</prop> <prop key="age">25</prop> </props> </property> </bean> </beans>
运行结果:
看到这边,大部分人都会觉得,每一个Bean都要这么操作一下,这么复杂,还不如直接写代码呢。
接下来,我们来简化配置。
先来简化配置:(新建一个配置文件:applicationContext_annotation.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:contest="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"> <!-- 将包 com.bing.tao.bean 下的Bean都交给Spring --> <contest:component-scan base-package="com.bing.tao.bean"></contest:component-scan> </beans>
将User修改成:
import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; /** * @Component 用于标记该bean需要Spring实例化。 * @Scope 标签用于标记该bean是单例还是多例,singleton表示单例,prototype多例。 */ @Component("user") @Scope(scopeName = "singleton") public class User { /** * @Value标签可以将括号中的值注入到Spring生成的Bean中 */ @Value("1") String id; @Value("蕾蕾") String name; @Value("123") String passWord; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassWord() { return passWord; } public void setPassWord(String passWord) { this.passWord = passWord; } public String toString(){ return"name: "+name+" id: "+id; } //构造后调用 @PostConstruct public void init(){ System.out.println("User初始化执行init方法!"); } //销毁前调用 @PreDestroy public void userDestroy(){ System.out.println("userDestroy方法被执行!"); } }
创建一个测试方法:
import com.bing.tao.bean.User; import org.junit.jupiter.api.Test; import org.springframework.context.support.ClassPathXmlApplicationContext; public class HelloSpring3 { @Test public void Test1(){ ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext_annotation.xml"); //通过getBean获取配置好的user对象(程序员向spring容器要对象) User user= (User) applicationContext.getBean("user"); System.out.println(user); //scope="singleton" 是单例下才能出发销毁bean方法,如果是多例则spring不在关联bean而是交给你管理。 applicationContext.close(); } }
运行结果:
这样就可以批量设置模式一样的Bean结构了。XML的配置就可以很好的简化。同时还倒逼了目录结构的整齐。
总结来源:http://www.sikiedu.com/ 网站学习。