spring创建对象的方式
spring可以帮助管理对象,需要的时候从spring容器中获取相应的对象即可,那么spring究竟是怎样创建对象的呢?下面介绍三种创建对象的方式
无参构造的方法(重点)
首先创建一个User类
public class User { private String name; private Integer age; 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; } }
然后在配置文件中配置相应的bean元素
<bean name="user" class="com.jinxin.spring.User"></bean>
最后获取该对象
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); User user = (User) ac.getBean("user");
静态工厂(了解)
首先创建一个User类,其中有一个静态方法 createUser() 是用来获取User对象的
public class User { private String name; private Integer age; public static User createUser() { return new User(); } 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; } }
然后在配置文件中配置调用createUser()方法来创建User对象放到容器中
1 <bean name="user1" class="com.jinxin.spring.User" factory-method="createUser"></bean>
获取该对象
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); User user1 = (User) ac.getBean("user1");
实例化工厂(了解)
首先创建一个User类,里面有一个非静态方法 createUser() 用来获取对象
public class User { private String name; private Integer age; public User createUser() { return new User(); } 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; } }
然后在配置文件中配置调用createUser()方法来获取User对象
1 <bean name="user2" factory-bean="userFactory" factory-method="createUser1"></bean> 2 <bean name="userFactory" class="com.jinxin.spring.User"></bean>
最后获取该user对象
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); User user1 = (User) ac.getBean("user2");
Spring属性注入
spring属性的注入分为四种,分别是
- set方法注入(重点)
- 构造方法的注入(重点)
- p名称空间注入(了解)
- spel注入(了解)
set方法注入
首先准备一个User类,里面有name,age以及car属性,其中Car是一个类,里面有name跟color属性
User类
public class User { private String name; private Integer age; private Car car; @Override public String toString() { // TODO Auto-generated method stub return this.name + "-" + this.age + "-" + this.car.getName() + "-" + this.car.getColor(); } 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 Car getCar() { return car; } public void setCar(Car car) { this.car = car; } }
Car类
public class Car { private String name; private String color; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } }
为User对象的name跟age属性注入值
使用property标签注入,其中name书要注入的属性名,value是为该属性注入什么值
1 <bean name="user" class="com.jinxin.spring.User"> 2 <property name="name" value="Eric"></property> 3 <property name="age" value="16"></property> 4 </bean>
为User对象的car属性注入值
上面介绍了为User的基本类型属性注入值,那么如果还有一个属性是自己定义的某一个类呢?还能使用同样的方式注入吗?当然不能,首先,应该先写出该类(Car类)的bean元素,然后在user的bean元素里面使用property标签进行注入,值得注意的是,property中的value字段应该替换成ref字段
1 <!-- 先配置car --> 2 <bean name="car" class="com.jinxin.spring.Car"> 3 <property name="name" value="兰博基尼"></property> 4 <property name="color" value="yellow"></property> 5 </bean> 6 7 <bean name="user" class="com.jinxin.spring.User"> 8 <!-- 然后使用ref关联上面的car对象 --> 9 <property name="car" ref="car"></property> 10 </bean>
构造方法的注入
在上面的User类中加入构造方法设置name,age跟car属性
public class User { private String name; private Integer age; private Car car; public User(String name, Integer age, Car car) { this.name = name; this.age = age; this.car = car; } @Override public String toString() { // TODO Auto-generated method stub return this.name + "-" + this.age + "-" + this.car.getName() + "-" + this.car.getColor(); } 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 Car getCar() { return car; } public void setCar(Car car) { this.car = car; } }
然后在配置文件中注入值
1 <bean name="car" class="com.jinxin.spring.Car"> 2 <property name="name" value="兰博基尼"></property> 3 <property name="color" value="yellow"></property> 4 </bean> 5 6 <bean name="user" class="com.jinxin.spring.User"> 7 <constructor-arg name="name" value="Scarlett"></constructor-arg> 8 <constructor-arg name="age" value="33"></constructor-arg> 9 <constructor-arg name="car" ref="car"></constructor-arg> 10 </bean>
上面通过constructor-arg标签就可以为构造方法注入属性值,但是这还不够,现在如果有两个构造方法,形参的数目类型一致,只是位置不同,那么该怎样确定究竟为那个构造方法注入属性值呢?这时需要引入一个新的字段,叫做index,通过指定参数的位置来确定执行哪一个构造方法
首先为User类指定两个构造方法,形参数目类型均一致
public class User { private String name; private Integer age; private Car car; public User(String name, Integer age, Car car) { this.name = name; this.age = age; this.car = car; System.out.println("构造一"); } public User(Integer age, String name, Car car) { this.name = name; this.age = age; this.car = car; System.out.println("构造二"); } @Override public String toString() { // TODO Auto-generated method stub return this.name + "-" + this.age + "-" + this.car.getName() + "-" + this.car.getColor(); } 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 Car getCar() { return car; } public void setCar(Car car) { this.car = car; } }
然后在配置文件中通过指定参数的位置来确定执行哪一个构造方法
1 <bean name="car" class="com.jinxin.spring.Car"> 2 <property name="name" value="兰博基尼"></property> 3 <property name="color" value="yellow"></property> 4 </bean> 5 6 <bean name="user" class="com.jinxin.spring.User"> 7 <constructor-arg name="name" value="Scarlett" index="1"></constructor-arg> 8 <constructor-arg name="age" value="33" index="0"></constructor-arg> 9 <constructor-arg name="car" ref="car" index="2"></constructor-arg> 10 </bean>
很显然,上面设置的参数顺序是age、 name、car,所以应该执行构造方法二
上面虽然通过确定参数的位置解决了确定参数类型数目相同的构造方法的问题,那么如何解决参数位置数目相同但是类型不同的问题呢?这需要引入另外一个字段type来指定参数的类型
首先在User类中准备两个构造方法,参数的数目以及位置都一致,只是一个name的类型是String,另一个name的类型是Integer
public class User { private String name; private Integer age; private Car car; public User(String name, Integer age, Car car) { System.out.println("构造一"); } public User(Integer name, Integer age, Car car) { System.out.println("构造二"); } @Override public String toString() { // TODO Auto-generated method stub return this.name + "-" + this.age + "-" + this.car.getName() + "-" + this.car.getColor(); } 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 Car getCar() { return car; } public void setCar(Car car) { this.car = car; } }
然后在配置文件中通过指定参数的类型来确定执行哪一个构造方法
1 <bean name="car" class="com.jinxin.spring.Car"> 2 <property name="name" value="兰博基尼"></property> 3 <property name="color" value="yellow"></property> 4 </bean> 5 6 <bean name="user" class="com.jinxin.spring.User"> 7 <constructor-arg name="name" value="100" type="java.lang.Integer"></constructor-arg> 8 <constructor-arg name="age" value="33"></constructor-arg> 9 <constructor-arg name="car" ref="car"></constructor-arg> 10 </bean>
很显然,上面执行的应该是name为Integer属性的构造方法
上面通过index跟type便能够具体到每一个构造方法
p命名空间注入(了解)
首先需要在beans里面导入p名称:xmlns:p="http://www.springframework.org/schema/p"
即
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xmlns="http://www.springframework.org/schema/beans" 4 xmlns:p="http://www.springframework.org/schema/p" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd "> 6 7 </bean>
然后在bean元素里面通过 p:属性名 进行注入
1 <bean name="car" class="com.jinxin.spring.Car"> 2 <property name="name" value="兰博基尼"></property> 3 <property name="color" value="yellow"></property> 4 </bean> 5 6 <bean name="user" class="com.jinxin.spring.User" p:name="taylor" p:age="27" p:car-ref="car"></bean> 7
spel注入(了解)
spel:spring expression language(spring表达式语言)
1 <bean name="user" class="com.jinxin.spring.User"> 2 <property name="name" value="Sam"></property> 3 <property name="age" value="18"></property> 4 </bean> 5 6 <bean name="car" class="com.jinxin.spring.Car"> 7 <property name="name" value="兰博基尼"></property> 8 <property name="color" value="yellow"></property> 9 </bean> 10 11 <!-- 将user的name属性的值作为user1的name属性的值 --> 12 <bean name="user1" class="com.jinxin.spring.User"> 13 <property name="name" value="#{user.name}"></property> 14 <property name="car" ref="car"></property> 15 </bean>
复杂类型注入
如果出现以下类型,应该怎样注入呢?
private Object[] arry; // 数组类型 private List list; // List类型 private Map map; // Map类型 private Properties prop;
这涉及到了复杂类型的注入,下面一一介绍注入方式
数组类型的注入
<bean name="" class=""> <property name="arry"> <array> <value>sxy</value> <value>nn</value> <ref bean="car" /> </array> </property> </bean>
List类型注入
<bean name="" class=""> <property name="list"> <list> <value>jack</value> <value>rose</value> <ref bean="car" /> </list> </property> </bean>
Map类型注入
<bean name="" class=""> <property name="map"> <map> <entry key="url" value="jdbc:mysql:///1806"></entry> <entry key="car" value-ref="car"></entry> <entry key-ref="car" value-ref="car"></entry> </map> </property> </bean>
properties注入
<bean name="" class=""> <property name="prop"> <props> <prop key="url">jdbc:mysql:///1806</prop> <prop key="driverClass">com.jdbc.mysqlDriver</prop> <prop key="userName">root</prop> </props> </property> </bean>
Bean元素
使用bean元素可以描述需要Spring容器管理的对象
name属性
给被管理的对象起个名字,获得对象时根据名称获取对象,可以重复,可以使用特殊字符
class属性
被管理对象的完整类名
id属性
与name属性作用一模一样,但是名称不能重复,不能使用特殊字符,在开发中应该尽量使用name属性
scope属性
<bean name="user" class="com.jinxin.bean.User" scope="singleton"></bean>
scope属性指定了创建对象的规则,一共有四个取值,分别是singletom、prototype、request、session
- singleton(重点,默认值):单例对象,被标识为单例的对象在Spring容器中只会创建一次
- prototype(重点):多例,被标识为多例的对象每次获得时才会创建,每次创建都是新的对象
- request(了解):在web环境下,对象与request生命周期一致
- session(了解):在web环境下,对象与session生命周期一致
注意:将struts2的action交给spring管理的时候,scope必须是prototype,因为每次请求都会创建一个新的action对象
初始化&销毁方法
配置一方法作为生命周期初始化方法,Spring会在对象创建之后立即调用
init-method (方法必须是 public void 类型)
配置一个方法作为生命周期的销毁方法,Spring关闭并销毁所有的对象前调用
destory-method (方法必须是 public void 类型)
准备一个User类,类中有两个方法分别作为初始化方法跟销毁方法
public class User{ public void init(){ System,out,println("我是初始化方法"); } public void destory(){ System,out,println("我是销毁方法"); } }
在配置文件中指定这两个方法为初始化方法跟销毁方法
1 <bean name="user" class="com.jinxin.spring.User" init-method="init" destory-method="destoey"></bean>
分模块化配置
在spring中,讲所有的bean元素都配置在一个文件里面,难免会很乱,将特定模块下的对象配置在特定的文件里面,最后将这些文件全部引入到src目录下的applicationContext.xml文件中即可
<import resource="com/jinxin/spring/user.xml">