一、bean 标签和管理对象细节
1.1 bean 标签
作用:
用于配置对象让spring来创建的。
默认情况下它调用的是类中的无参构造函数。如果没有无参构造函数则不能创建成功。
属性:
id:给对象在容器中提供一个唯一标识。用于获取对象。
class:指定类的权限定类名。用于反射创建对象。默认情况下调用无参构造函数。
scope:指定对象的作用范围。
* singleton:默认值,单例的。
* prototype:多例的
init-method:指定类中的初始化方法名称。
destory-method:指定类中销毁方法名称。
1.2 bean的作用范围和生命周期
单列对象:scope="singleton"
一个应用只有一个对象的实例。它的作用范围就是整个引用。
生命周期:
对象出生:当应用加载时,创建容器时,对象就被创建了。
对象活着:只有容器在,对象一直活着。
对象死亡:当应用卸载,销毁容器时,对象就被销毁了。
多例对象:scope="prototype"
每次访问对象时,都会重新创建对象实例。
生命周期:
对象出生:当使用对象时,创建新的对象实例。
对象活着:只要对象在使用中,就一直活着。
对象死亡:当对象长时间不用时,被java的垃圾回收器回收了。
演示:单例和多例对象
第一步:编写IUserService接口
1 package com.justnow.service; 2 3 public interface IUserService { 4 public void findAll(); 5 }
第二步:编写UserServiceImpl实现类
1 package com.justnow.service.impl; 2 3 import com.justnow.service.IUserService; 4 5 public class UserServiceImpl implements IUserService { 6 7 public void findAll() { 8 System.out.println("假装打印了数据库中的所有数据"); 9 } 10 }
第三步:编写spring配置文件
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.xsd"> 6 <!--配置 service --> 7 <bean id="userService" class="com.justnow.service.impl.UserServiceImpl" scope="singleton"/> 8 </beans>
这里配置scope为单例对象
第四步:测试
1 package com.justnow.test; 2 3 import com.justnow.service.IUserService; 4 import org.junit.Test; 5 import org.springframework.context.support.ClassPathXmlApplicationContext; 6 7 public class Test01 { 8 @Test 9 public void testBean(){ 10 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); 11 IUserService userService = (IUserService) context.getBean("userService"); 12 IUserService userService1 = (IUserService) context.getBean("userService"); 13 System.out.println(userService); 14 System.out.println(userService1); 15 } 16 }
单例测试结果:
userService和userService2,打印出来的结果是一致的!
双例测试结果:
修改scope为"prototype"
1.3 实例化bean的三种方式
第一种方式:使用默认无参构造函数
会根据默认无参构造函数来创建类对象。如果bean中没有默认无参构造函数,将会创建失败。
如:
1 <bean id="userService" class="com.justnow.service.impl.UserServiceImpl" />
此时UserServiceImpl中必须有无参的构造函数。
第二种方式:spring管理静态工厂-使用静态工厂的方法创建对象
模拟一个静态工厂,创建业务层实现类
1 package com.justnow.factory; 2 3 import com.justnow.service.IUserService; 4 import com.justnow.service.impl.UserServiceImpl; 5 6 public class StaticFactory { 7 public static IUserService createUserService(){ 8 return new UserServiceImpl(); 9 } 10 }
bean的配置,使用StaticFactory类中的静态方法createUserService创建对象,并存入spring容器:
id 属性:指定bean的id,用于从容器中获取
class属性:指定静态工厂的全限定类名
factory-method 属性:指定生产对象的静态方法
1 <bean id="userService" class="com.justnow.factory.StaticFactory" factory-method="createUserService" />
第三种方式:spring管理实例工厂-使用实例工厂的方法创建对象
先把工厂的创建交给spring来管理。然后在使用工厂的bean来调用里面的方法
factory-bean属性:用来指定实例工厂beand的id。
factory-method属性:用于指定实例工厂中创建对象的方法。
模拟一个实例工厂,创建业务层实现类
此工厂创建对象,必须现有工厂实例对象,再调用方法
1 package com.justnow.factory; 2 3 import com.justnow.service.IUserService; 4 import com.justnow.service.impl.UserServiceImpl; 5 6 /** 7 * 模拟一个实例工厂,创建业务层实现类 8 * 此工厂创建对象,必须有工厂实例对象,再调用方法 9 */ 10 public class InstanceFactory { 11 public IUserService createUserService(){ 12 return new UserServiceImpl(); 13 } 14 }
bean的配置文件
<!--第三种方式,spring管理实例工厂,使用实例工厂的方法创建对象--> <bean id="instanceFactory" class="com.justnow.factory.InstanceFactory"/> <bean id="userService" factory-bean="instanceFactory" factory-method="createUserService" />
https://github.com/justn0w/javawebdemo/tree/master/spring/Spring_demo2
d20c371406409b204c554c0a41c91ad5b6b86de1
二、spring的依赖注入
2.1 什么是依赖注入:
依赖注入:Dependency Injection。它是spring框架核心IoC的具体实现。
我们的程序在编写时,通过控制反转,把对象的创建交给了spring,但是在代码中不可能出现没有依赖的情况。IoC解耦只是降低他们的依赖关系。
但不会消除。例如:我们的业务层仍会调用持久层的方法。简单的说就是spring框架把持久层对象传入业务层,而不用我们自己去获取。
2.2 通过构造函数实现依赖注入
使用类中的构造函数,给成员变量赋值。赋值操作是由spring框架来为我们注入的。
UserServiceImpl实现类:
该类共有三个属性,分别是name,age,birthday;
1 package com.justnow.service.impl; 2 3 import com.justnow.service.IUserService; 4 5 import java.util.Date; 6 7 public class UserServiceImpl implements IUserService { 8 9 private String name; 10 private Integer age; 11 private Date birthdy; 12 13 public UserServiceImpl() { 14 } 15 16 public UserServiceImpl(String name, Integer age, Date birthdy){ 17 this.name = name; 18 this.age = age; 19 this.birthdy = birthdy; 20 } 21 22 public void save(){ 23 System.out.println(name+","+age+","+birthdy); 24 } 25 26 /* public void findAll() { 27 System.out.println("假装打印了数据库中的所有数据"); 28 }*/ 29 }
在配置文件中赋值:
applicationContext.xml
1 <!--通过构造函数实现依赖注入--> 2 <bean id="userService" class="com.justnow.service.impl.UserServiceImpl" > 3 <constructor-arg name="name" value="张三"></constructor-arg> 4 <constructor-arg name="age" value="18"></constructor-arg> 5 <constructor-arg name="birthdy" ref="now"></constructor-arg> 6 </bean> 7 <bean id="now" class="java.util.Date" />
使用构造函数的方式,给service中的属性赋值
要求:类中需要提供一个对应参数列表的构造函数
标签:constructor-arg
属性:index:指定参数在构造函数列表的索引位置
type:指定参数在构造函数中的数据类型
name:指定参数在构造函数中的名称
value:给name属性赋值,前提是基本数据类型和String类型
ref:同样的是给name赋值,但是该值是bean类型,必须在配置文件中配置。如上例中的id为now的bean标签
本小节代码:
https://github.com/justn0w/javawebdemo/tree/master/spring/Spring_demo2
2e64f8d7cf0a7a1f710e8abfc3d9707653b5063a
2.2 set 方法注入
在UserServiceImpl实现类中,设置属性的set的方法即可代码,如下:
1 package com.justnow.service.impl; 2 3 import com.justnow.service.IUserService; 4 5 import java.util.Date; 6 7 public class UserServiceImpl implements IUserService { 8 9 private String name; 10 private Integer age; 11 private Date birthdy; 12 13 //set 方法注入 14 public void setName(String name) { 15 this.name = name; 16 } 17 18 public void setAge(Integer age) { 19 this.age = age; 20 } 21 22 public void setBirthdy(Date birthdy) { 23 this.birthdy = birthdy; 24 } 25 26 public void save(){ 27 System.out.println(name+","+age+","+birthdy); 28 } 29 30 }
同时还需要修改spring的配置文件
1 <!--通过set方法实现依赖注入--> 2 <!-- 通过配置文件给 bean 中的属性传值:使用 set 方法的方式 3 涉及的标签: 4 property 5 属性: 6 name:找的是类中 set 方法后面的部分 7 ref:给属性赋值是其他 bean 类型的 8 value:给属性赋值是基本数据类型和 string 类型的 9 实际开发中,此种方式用的较多。 10 --> 11 <bean id="userService" class="com.justnow.service.impl.UserServiceImpl"> 12 <property name="name" value="test"/> 13 <property name="age" value="21"/> 14 <property name="birthdy" ref="now" /> 15 </bean> 16 17 <bean id="now" class="java.util.Date" />
测试结果:
https://github.com/justn0w/javawebdemo/tree/master/spring/Spring_demo2
fe6038b18cff7d32c1b4515bf53bea9c8b0bdd0e
2.2 使用p名称空间注入数据
在xml中导入p名称空间,使用p:propertyName来注入数据,本质仍然是调用类中的set方法实现注入功能。
所以,UserServiceIpml实现类,不需要改变。只需要修改spring的配置文件即可
第一步:修改xml的命名空间,即添加p命名空间
添加了一句:
xmlns:p="http://www.springframework.org/schema/p"
第二步:在bean中使用p标签给属性赋值
1 <bean id="userService" class="com.justnow.service.impl.UserServiceImpl" p:name="testp" p:age="23" p:birthdy-ref="now"/> 2 <bean id="now" class="java.util.Date" />
测试结果:
47e50fff82f0cee3155226f620a00989da3828a6
2.3 注入集合属性
考虑到某些情况下需要一些类型为集合的属性,接下来就演示下,如何注入集合属性的。其本质还是通过set方法注入属性的
第一步:在实现类中添加数组、List、set、Map、Properties等数据类型的属性。
1 package com.justnow.service.impl; 2 3 import com.justnow.service.IUserService; 4 5 import java.util.*; 6 7 public class UserServiceImpl2 implements IUserService { 8 9 private String[] myStrs; 10 private List<String> myList; 11 private Set<String> mySet; 12 private Map<String, String> myMap; 13 private Properties myProps; 14 15 public void setMyStrs(String[] myStrs) { 16 this.myStrs = myStrs; 17 } 18 19 public void setMyList(List<String> myList) { 20 this.myList = myList; 21 } 22 23 public void setMySet(Set<String> mySet) { 24 this.mySet = mySet; 25 } 26 27 public void setMyMap(Map<String, String> myMap) { 28 this.myMap = myMap; 29 } 30 31 public void setMyProps(Properties myProps) { 32 this.myProps = myProps; 33 } 34 35 36 public void save() { 37 System.out.println(Arrays.toString(myStrs)); 38 System.out.println(myList); 39 System.out.println(mySet); 40 System.out.println(myMap); 41 System.out.println(myProps); 42 } 43 }
第二步:修改spring配置文件
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 xmlns:p="http://www.springframework.org/schema/p" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans.xsd"> 7 <!--配置 service --> 8 <!-- 第一种方式,使用默认无参构造函数 9 <bean id="userService" class="com.justnow.service.impl.UserServiceImpl" scope="prototype"/> 10 --> 11 <!--第二种方式,spring管理静态工厂-使用静态工厂的方法对象创建--> 12 <!-- 13 <bean id="userService" class="com.justnow.factory.StaticFactory" factory-method="createUserService" /> 14 --> 15 <!--第三种方式,spring管理实例工厂,使用实例工厂的方法创建对象--> 16 <!-- 17 <bean id="instanceFactory" class="com.justnow.factory.InstanceFactory"/> 18 <bean id="userService" factory-bean="instanceFactory" factory-method="createUserService" /> 19 --> 20 21 <!--通过构造函数实现依赖注入--> 22 <!-- 23 <bean id="userService" class="com.justnow.service.impl.UserServiceImpl" > 24 <constructor-arg name="name" value="张三"></constructor-arg> 25 <constructor-arg name="age" value="18"></constructor-arg> 26 <constructor-arg name="birthdy" ref="now"></constructor-arg> 27 </bean> 28 <bean id="now" class="java.util.Date" /> 29 --> 30 <!--通过set方法实现依赖注入--> 31 <!-- 通过配置文件给 bean 中的属性传值:使用 set 方法的方式 32 涉及的标签: 33 property 34 属性: 35 name:找的是类中 set 方法后面的部分 36 ref:给属性赋值是其他 bean 类型的 37 value:给属性赋值是基本数据类型和 string 类型的 38 实际开发中,此种方式用的较多。 39 40 <bean id="userService" class="com.justnow.service.impl.UserServiceImpl"> 41 <property name="name" value="test"/> 42 <property name="age" value="21"/> 43 <property name="birthdy" ref="now" /> 44 </bean> 45 46 <bean id="now" class="java.util.Date" /> 47 --> 48 <!--使用p命名空间--> 49 <!-- 50 <bean id="userService" class="com.justnow.service.impl.UserServiceImpl" p:name="testp" p:age="23" p:birthdy-ref="now"/> 51 <bean id="now" class="java.util.Date" /> 52 --> 53 <!-- 注入集合数据 54 List 结构的: 55 array,list,set 56 Map 结构的 57 map,entry,props,prop 58 --> 59 <bean id="userService" class="com.justnow.service.impl.UserServiceImpl2"> 60 <!-- 在注入集合数据时,只要结构相同,标签可以互换 --> 61 <!-- 给数组注入数据 --> 62 <property name="myStrs"> 63 <array> 64 <value>AAA</value> 65 <value>BBB</value> 66 <value>CCC</value> 67 </array> 68 </property> 69 <!-- 注入 list 集合数据 --> 70 <property name="myList"> 71 <list> 72 <value>AAA</value> 73 <value>BBB</value> 74 <value>CCC</value> 75 </list> 76 </property> 77 <!-- 注入 set 集合数据 --> 78 <property name="mySet"> 79 <set> 80 <value>AAA</value> 81 <value>BBB</value> 82 <value>CCC</value> 83 </set> 84 </property> 85 <!-- 注入 Map 数据 --> 86 <property name="myMap"> 87 <props> 88 <prop key="testA">aaa</prop> 89 <prop key="testB">bbb</prop> 90 </props> 91 </property> 92 <!-- 注入 properties 数据 --> 93 <property name="myProps"> 94 <map> 95 <entry key="testA" value="aaa"></entry> 96 <entry key="testB"> 97 <value>bbb</value> 98 </entry> 99 </map> 100 </property> 101 </bean> 102 </beans>
77a345e6da51295e1aa4c5e8c25038e23da3f6ec
总结:
1、这些内容在将来的开发过程中会很少用到,但是,还是梳理一下。