【Java EE 学习 49 上】【Spring学习第一天】【基本配置】
一、HelloWorld
需要的jar文件(以2.5.5为例):spring.jar,common-logging.jar
1.新建类com.kdyzm.spring.helloworld.HelloWorld.java
1 package com.kdyzm.spring.helloworld; 2 3 public class HelloWorld { 4 public void say(){ 5 System.out.println("Hello,World!"); 6 } 7 }
2.新建配置文件com.kdyzm.spring.helloworld.applicationContext.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans 5 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> 6 <!-- 注册HelloWorld --> 7 <bean id="helloWorld" class="com.kdyzm.spring.helloworld.HelloWorld"></bean> 8 </beans>
beans标签:对应着spring容器。
bean标签:对应着一个类,id是唯一标识符,class是类路径。
3.新建测试文件HelloWorld.spring.HelloWorldTest.java
1 package com.kdyzm.spring.helloworld; 2 3 import org.springframework.context.ApplicationContext; 4 import org.springframework.context.support.ClassPathXmlApplicationContext; 5 6 public class HelloWorldTest { 7 public static void main(String[] args) { 8 //测试HelloWorld 9 ApplicationContext context=new ClassPathXmlApplicationContext("com/kdyzm/spring/helloworld/applicationContext.xml"); 10 HelloWorld helloWorld = (HelloWorld) context.getBean("helloWorld"); 11 helloWorld.say(); 12 } 13 }
4.运行结果:
Hello,World!
二、别名
在beans标签下,使用alias标签为bean指定别名,指定别名的好处就是在不同的模块下使用不同的名字,增强可读性。
<bean id="helloWorld" class="com.kdyzm.spring.helloworld.HelloWorld"></bean> <alias name="helloWorld" alias="狗蛋"/> <alias name="helloWorld" alias="张三"/>
测试:
ApplicationContext context=new ClassPathXmlApplicationContext("com/kdyzm/spring/helloworld/applicationContext.xml"); HelloWorld helloWorld=(HelloWorld) context.getBean("狗蛋"); helloWorld.say();
三、spring创建对象
1.spring默认在启动spring容器的时候见所有bean都提前进行实例化。提前实例化意味着作为初始化的一部分,ApplicationContext会自动创建并且配置所有的singleton bean。通常情况下这是件好事,因为这样在配置中在有任何错误能够立即发现。
使用lazy-init="true"属性能够开启懒加载,这样初始化bean的时候的时机就变为在调用类中方法的时候。默认为false,禁用懒加载。
2.使用静态工厂方法创建对象
(1)首先创建一个工厂类com.kdyzm.spring.helloworld.HelloWorldFactory.java
1 package com.kdyzm.spring.helloworld; 2 /* 3 * 静态工厂类 4 */ 5 public class HelloWorldFactory { 6 public static HelloWorld getInstance(){ 7 return new HelloWorld(); 8 } 9 }
(2)在com.kdyzm.spring.helloworld.applicationContext.xml配置文件中配置
<bean id="helloWorldFactory" class="com.kdyzm.spring.helloworld.HelloWorldFactory" factory-method="getInstance"></bean>
使用factory-method属性声明使用工厂里的那个方法生成目标对象
(3)测试
ApplicationContext context=new ClassPathXmlApplicationContext("com/kdyzm/spring/helloworld/applicationContext.xml"); HelloWorld helloWorld=(HelloWorld) context.getBean("helloWorldFactory"); helloWorld.say();
直接使用getBean方法获取HelloWorld对象即可。
3.默认情况下使用spring创建对象是单例模式,这种方式创建独享非常容易出现安全性问题。使用bean标签的scope属性解决该问题。
* singleton:默认的方式,单例,属性共享(一般情况下应当将数据放到方法的变量中)
* prototype:多例,当一个bean是多例模式的情况下,lazy-init为false或者default无效,也就是说懒加载强制开启。
配置示例:
<bean id="helloWorld" class="com.kdyzm.spring.scope.HelloWorld" scope="prototype"></bean>
一旦使用多例模式,创建的每个对象在内存中都是独一无二的。
4.指定Bean的初始化方法和销毁方法。
spring在初始化bean或者销毁bean的时候有时候需要做一些处理工作,因此spring可以在创建和拆卸bean的时候调用bean的两个生命周期方法。
applicationContext.xml配置:
<bean id="helloWorld" class="com.kdyzm.spring.createObject.HelloWorld" init-method="init" destroy-method="destroy" > </bean>
HelloWorld配置:
1 package com.kdyzm.spring.createObject; 2 3 public class HelloWorld { 4 public void init(){ 5 System.out.println("初始化方法被调用!"); 6 } 7 public HelloWorld() { 8 System.out.println("构造方法被调用!"); 9 } 10 public void say(){ 11 System.out.println("HelloWorld!"); 12 } 13 public void destroy(){ 14 System.out.println("销毁方法被调用!"); 15 } 16 }
测试方法:
ApplicationContext context=new ClassPathXmlApplicationContext("com/kdyzm/spring/createObject/applicationContext.xml"); System.out.println("spring容器已经启动!"); HelloWorld helloWorld=(HelloWorld) context.getBean("helloWorld"); helloWorld.say(); ClassPathXmlApplicationContext applicationContext=(ClassPathXmlApplicationContext)context; applicationContext.close();
将ApplicationContext的引用对象转换成ClassPathXmlApplicationContext对象,调用close方法之后对象才会调用destroy方法。
总结:
* init-method:该方法被spring容器执行,在构造方法之后执行,如果需要在构造方法之后,调用方法之前做一些工作,可以在init方法中完成。
* destroy-method:
如果该bean是单例的,则在spring容器关闭或者销毁的时候,执行该方法
如果该bean是多例的,则spring容器不负责销毁。
所以,要想让spring容器控制住bean的生命周期,那么该bean必须是单例的;如果该bean是多例的,那么关闭资源的操作应当由程序员完成。
四、依赖注入(DI)
什么是依赖注入:当使用spring创建对象的同时给对象中的属性赋初值。
1.使用构造器注入
(1)可以通过参数的顺序依次确定给其赋初值
<constructor-arg index="0"> <value>张三</value> </constructor-arg> <constructor-arg index="1"> <value>56</value> </constructor-arg>
(2)可以通过参数的类型给其赋初值
<constructor-arg type="java.lang.Integer"> <value>56</value> </constructor-arg> <constructor-arg type="java.lang.String"> <value>张三</value> </constructor-arg>
(3)可以根据参数的顺序和类型共同确定某个属性
<bean id="person" class="com.kdyzm.spring.di.Person"> <constructor-arg index="0" type="java.lang.String" value="小强"></constructor-arg> <constructor-arg index="1" type="java.lang.String" value="12110501001"></constructor-arg> </bean>
测试(3):
1 package com.kdyzm.spring.di; 2 3 public class HelloWorld { 4 private String name; 5 private Person p; 6 7 public HelloWorld(String name, Person p) { 8 this.name = name; 9 this.p = p; 10 } 11 public HelloWorld() { 12 System.out.println("HelloWorld对象被创建!"); 13 } 14 public void say() { 15 System.out.println(name+":"+p); 16 } 17 }
1 package com.kdyzm.spring.di; 2 3 public class Person { 4 private String name; 5 private String id; 6 public Person(String name, String id) { 7 this.name = name; 8 this.id = id; 9 } 10 public Person() { 11 } 12 @Override 13 public String toString() { 14 return "Person [name=" + name + ", id=" + id + "]"; 15 } 16 public String getName() { 17 return name; 18 } 19 public void setName(String name) { 20 this.name = name; 21 } 22 public String getId() { 23 return id; 24 } 25 public void setId(String id) { 26 this.id = id; 27 } 28 }
测试代码:
ApplicationContext context=new ClassPathXmlApplicationContext("com/kdyzm/spring/di/applicationContext.xml"); HelloWorld helloWorld=(HelloWorld) context.getBean("helloWorld"); helloWorld.say();
运行结果:
狗蛋:Person [name=小强, id=12110501001]
2.使用setting方法进行注入(推荐使用的方法)
(1)简单的数据类型:包装类型和String
<bean id="personService" class="com.itcast.bean.impl.PersonServiceImpl"> <!-- 基本类型,string类型 --> <property name="age" value="20"></property> <property name="name" value="张无忌"></property> </bean>
(2)引用其它bean
<bean id="person" class="com.itcast.bean.Person" /> <bean id="personService" class="com.itcast.bean.impl.PersonServiceImpl"> <property name="person" ref="person" /> </bean>
(3)装配List集合。
<property name="lists"> <list> <value>list1</value> <value>list2</value> <ref bean="student"/> </list> </property>
(4)装配Set集合
<property name="sets"> <set> <value>set1</value> <value>set2</value> <ref bean="student"/> </set> </property>
(5)装配Map
<property name="maps"> <map> <entry key="01"> <value>map01</value> </entry> <entry key="02"> <value>map02</value> </entry> </map> </property>
(6)装配Properties
<property name="props"> <props> <prop key="01">prop1</prop> <prop key="02">prop2</prop> </props> </property>
(7)小练习:
1 package com.kdyzm.spring.di.setting; 2 3 import java.util.List; 4 import java.util.Map; 5 import java.util.Set; 6 7 public class Person { 8 private String name; 9 private Integer num; 10 private Student student; 11 private List<Student>list; 12 private Set<Student>set; 13 private Map<String,Student>map; 14 public Person() { 15 System.out.println("Person对象被创建!"); 16 } 17 public void setName(String name) { 18 this.name = name; 19 } 20 public void setNum(Integer num) { 21 this.num = num; 22 } 23 public void setStudent(Student student) { 24 this.student = student; 25 } 26 public void setList(List<Student> list) { 27 this.list = list; 28 } 29 public void setSet(Set<Student> set) { 30 this.set = set; 31 } 32 public void setMap(Map<String, Student> map) { 33 this.map = map; 34 } 35 @Override 36 public String toString() { 37 return "Person [name=" + name + ", num=" + num + ", student=" + student 38 + ", list=" + list + ", set=" + set + ", map=" + map + "]"; 39 } 40 }
1 package com.kdyzm.spring.di.setting; 2 3 public class Student { 4 private String id; 5 private String name; 6 public Student(String id, String name) { 7 this.id = id; 8 this.name = name; 9 } 10 public Student() { 11 System.out.println("Student对象被创建!"); 12 } 13 @Override 14 public String toString() { 15 return "Student [id=" + id + ", name=" + name + "]"; 16 } 17 public String getId() { 18 return id; 19 } 20 public void setId(String id) { 21 this.id = id; 22 } 23 public String getName() { 24 return name; 25 } 26 public void setName(String name) { 27 this.name = name; 28 } 29 }
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans 5 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> 6 <bean id="person" class="com.kdyzm.spring.di.setting.Person"> 7 <property name="name" value="小黄"></property> 8 <property name="num" value="123456"></property> 9 <property name="student" ref="student"></property> 10 <property name="list"> 11 <list> 12 <ref bean="student"/> 13 <ref bean="student"/> 14 </list> 15 </property> 16 <property name="set"> 17 <set> 18 <ref bean="student"/> 19 <ref bean="student"/> 20 </set> 21 </property> 22 <property name="map"> 23 <map> 24 <entry key="张三" value-ref="student"></entry> 25 <entry key="李四" value-ref="student"></entry> 26 <entry key="王五" value-ref="student"></entry> 27 </map> 28 </property> 29 </bean> 30 <bean id="student" class="com.kdyzm.spring.di.setting.Student"> 31 <property name="id" value="1"></property> 32 <property name="name" value="小强"></property> 33 </bean> 34 </beans>
测试代码:
ApplicationContext context=new ClassPathXmlApplicationContext("com/kdyzm/spring/di/setting/applicationContext.xml"); Person person=(Person) context.getBean("person"); System.out.println(person);
运行结果:
Person对象被创建!
Student对象被创建!
Person [name=小黄, num=123456, student=Student [id=1, name=小强], list=[Student [id=1, name=小强], Student [id=1, name=小强]], set=[Student [id=1, name=小强]], map={张三=Student [id=1, name=小强], 李四=Student [id=1, name=小强], 王五=Student [id=1, name=小强]}]