目录
3.3 applicationContext和BeadFactory
一、spring介绍
spring是一个分层的一站式的轻量级开源框架,其实就是一个容器,里边存了各种各样的对象,就是一个大工厂,可以将所有对象创建和依赖关系维护,交给spring管理。
正式因为spring框架性质是容器性质的,容器中装什么对象就有什么功能。所以可以一站式。
不仅不排斥其他框架,还能帮其他框架管理对象。
aop支持,ioc思想,spring jdbc,事务,junit测试支持等等。
二、spring框架搭建
spring框架包含了很多包,大致的可以分为上述的几个模块,数据层,web层,切面,其中下边那四个包是核心基础包
我们需要引入这四个包 beans,core,context,spring-expression
spring要依赖一个日志组件
低版本的spring 依赖log4j 日志组件 com.springsource.org.apache.log4j-1.2.15.jar 可选,高版本依赖前边那个
2.1 创建一个web工程
添加相关jar包,添加配置文件applicationContext.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-4.2.xsd ">
<!-- 将User对象交给spring容器管理 -->
<!-- Bean元素:使用该元素描述需要spring容器管理的对象
class属性:被管理对象的完整类名.
name属性:给被管理的对象起个名字.获得对象时根据该名称获得对象.
可以重复.可以使用特殊字符.
id属性: 与name属性一模一样.
名称不可重复.不能使用特殊字符.
结论: 尽量使用name属性.
-->
<bean name="user" class="cn.itcast.bean.User" ></bean>
</beans>
添加cn.itcast.bean.User
package cn.itcast.bean;
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;
}
@Override
public String toString() {
return "User [name=" + name + ", age=" + age + "]";
}
}
添加测试代码
package cn.itcast.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import cn.itcast.bean.User;
public class TestDemo {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User)context.getBean("user");
System.out.println(user);
}
}
运行后可以打印出user对象,这里的对象很明显不是自己new的,是从容器中获取的。
三、spring的中的概念
3.1 IOC 控制反转
ioc:inverse of control 意思就是将我们创建对象的方式翻转了
以前对象的创建都是由我们开发人员自己维护,包括依赖关系,使用了spring之后,对象的创建以及依赖关系可以由spring完成创建以及注入
控制反转 其实是反转了对象的创建方式,从我们自己创建对象给程序 转变为 程序自己创建对象。
3.2 DI 依赖注入
di:dependency injection 依赖注入,是一种实现技术,实现ioc思想需要di做支持,di 是程序创建对象的一种方式,所以可以说是实现ioc思想的一种技术
注入方式:
set 方法注入,构造方法注入
注入类型:
值类型注入,引用类型注入
3.3 applicationContext和BeadFactory
3.3.1 BeanFactory 接口
这是spring提供的原始的接口,当初设计的时候环境不一样,功能也比较单一,BeanFactory接口实现类的容器,特点是每次在获得对象的时候才会创建对象,因为当时的电脑配置啥的资源都比较匮乏。
3.3.2 ApplicationContext接口
每次容器启动时就会创建容器中配置的所有对象,并提供更多功能,目前有两个实现类
从类路径下加载配置文件:ClassPathXmlApplicationContext
从硬盘绝对路径下加载配置文件:FileSystemXmlApplicationContext
在web开发中,一般使用ApplicationContext来获取对象,在资源匮乏或者不想占用很多内存的情况下使用BeanFactory来获取对象
四、spring配置详解
4.1 Bean元素
使用该标签(元素) 来描述需要spring管理的对象
class属性:被管理对象的完全限定类名。
name属性:被管理对象的名字,获取对象的时候用,名称可以重复,可以使用特殊字符。
id属性:与name属性一模一样,名称不可重复,不能使用特殊字符。
一般使用name属性区分对象
4.2 Bean元素进阶
4.2.1 scope属性:对象的生命周期
singleton(默认值):单例对象,这类对象在spring容器中只会存在一个实例
代码如下:
<bean name="user" class="cn.itcast.bean.User" scope="singleton" ></bean>
@Test
public void testScopeSingleton() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"applicationContext.xml");
User user = (User) context.getBean("user");
User user1 = (User) context.getBean("user");
User user2 = (User) context.getBean("user");
User user3 = (User) context.getBean("user");
System.out.println(user);
System.out.println(user1);
System.out.println(user2);
System.out.println(user3);
System.out.println(user3 == user1);
}
prototype(多例的),这类对象在每次获得的时候才会创建,每次获取都是新的对象,整合struts2时,ActionBean必须配置为多例的
代码如下:
<bean name="user1" class="cn.itcast.bean.User" scope="prototype" ></bean>
public void testScopePrototype() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"applicationContext.xml");
User user = (User) context.getBean("user1");
User user1 = (User) context.getBean("user1");
User user2 = (User) context.getBean("user1");
User user3 = (User) context.getBean("user1");
System.out.println(user);
System.out.println(user1);
System.out.println(user2);
System.out.println(user3);
System.out.println(user3 == user1);
}
request(当前请求的),适用于web环境下,对象与request的生命周期一致。
session(当前回话的),适用于web环境下,对象与session的生命周期一致。
4.2.2 生命周期属性
可以为对象配置init-method 和destroy-method方法,这样spring在创建和销毁对象的时候会自动调用这两个方法
<bean name="user" class="cn.itcast.bean.User" scope="singleton"
init-method="initUser" destroy-method="destroyUser" ></bean>
@Test
public void testLift() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
"applicationContext.xml");
User user = (User) context.getBean("user");
System.out.println(user);
context.close();
}
4.3 spring创建对象的方式
4.3.1 空参构造方式
加入一个无参构造函数
public User() {
System.out.println("空参构造函数被调用。。。。");
}
@Test
public void testLift() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
"applicationContext.xml");
//User user = (User) context.getBean("user");
//System.out.println(user);
}
直接创建容器的时候就创建了对象,所以就调用了构造函数。
4.3.2 静态工厂
<bean name="user" class="cn.itcast.factory.UserFactory" factory-method="getUser"></bean>
class指定为工厂类,使用factory-method属性 配置获取对象的方法为getUser
package cn.itcast.factory;
import cn.itcast.bean.User;
public class UserFactory {
public static User getUser(){
System.out.println("静态工厂模式创建");
return new User();
}
}
@Test
public void testFactory() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
"applicationContext.xml");
User user = (User) context.getBean("user");
System.out.println(user);
}
4.3.3 实例工厂模式
添加一个getUser1的实例方法
package cn.itcast.factory;
import cn.itcast.bean.User;
public class UserFactory {
// public static User getUser(){
// System.out.println("静态工厂模式创建");
// return new User();
// }
//
public User getUser1(){
System.out.println("实例工厂模式创建");
return new User();
}
}
<bean name="user" class="cn.itcast.bean.User" factory-bean="UserFactory"
factory-method="getUser1"></bean>
<bean name="userFactory" class="cn.itcast.factory.UserFactory"></bean>
指定factory-bean 并要配置工厂类
4.4 分模块配置
当spring 配置的bean越来越多的时候,不容易维护和管理,我们可以分模块写到其他配置文件中,然后再引入这个配置文件
<import resource="cn/itcast/springconfig/applicationContext.xml"/>
这样的话我们就可以获取到其他配置文件里的对象
五、spring属性注入
5.1 注入方式
5.1.1 set方法注入
添加一个car类
package cn.itcast.bean;
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类添加一个car属性
package cn.itcast.bean;
public class User {
private String name;
private Integer age;
private Car car;
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
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 void initUser(){
System.out.println("user init ...");
}
public void destroyUser(){
System.out.println("user destroy ...");
}
@Override
public String toString() {
return "User [name=" + name + ", age=" + age + ", car=" + car + "]";
}
}
<bean name="user" class="cn.itcast.bean.User">
<property name="name" value="zhangsan"></property>
<property name="age" value="25"></property>
<!-- 引用类型属性用ref 来指定一个bean -->
<property name="car" ref="car"></property>
</bean>
<bean name="car" class="cn.itcast.bean.Car">
<property name="name" value="兰博基尼"></property>
<property name="color" value="红色"></property>
</bean>
5.1.2 构造函数注入
添加一个构造函数
public User(Integer age, Car car) {
System.out.println("构造函数注入。。");
this.age = age;
this.car = car;
}
<bean name="car" class="cn.itcast.bean.Car">
<property name="name" value="兰博基尼"></property>
<property name="color" value="红色"></property>
</bean>
<bean name="user" class="cn.itcast.bean.User">
<constructor-arg name="age" index="0" value="26" type="java.lang.Integer"></constructor-arg>
<constructor-arg name="car" index="1" ref="car" ></constructor-arg>
</bean>
构造函数由于其参数个数,位置,类型都不一样而可能出现多个构造函数,所有我们要对参数进行限制来准确定位构造函数
其中有index type 属性可以使用表示 参数的索引和类型
5.1.3 p名称空间注入
这种注入方式是spring新发明的,使用起来较为简单,但是基本没人用。因为人们已经习惯了之前的那种注入方式。
首先需要导入名称空间 xmlns:p="http://www.springframework.org/schema/p"
<bean name="user" class="cn.itcast.bean.User" p:name="p名称空间" p:age="23" >
</bean>
六、复杂类型注入
6.1 创建一个复杂类型
package cn.itcast.bean;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;
public class CollectionBean {
private Object[] arr;
private List list;
private Map map;
private Properties properties;
public Object[] getArr() {
return arr;
}
public void setArr(Object[] arr) {
this.arr = arr;
}
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
public Map getMap() {
return map;
}
public void setMap(Map map) {
this.map = map;
}
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
@Override
public String toString() {
return "CollectionBean [arr=" + Arrays.toString(arr) + ", list=" + list
+ ", map=" + map + ", properties=" + properties + "]";
}
}
6.2 配置数组属性注入
<bean name="collectionBean" class="cn.itcast.bean.CollectionBean">
<property name="arr">
<array>
<value>tom</value>
<value>23</value>
<ref bean="user"/>
</array>
</property>
</bean>
6.3 配置集合属性注入
<bean name="collectionBean" class="cn.itcast.bean.CollectionBean">
<property name="arr">
<array>
<value>tom</value>
<value>23</value>
<ref bean="user"/>
</array>
</property>
<property name="list">
<list>
<value>jerry</value>
<value>哈哈</value>
<ref bean="user"/>
</list>
</property>
</bean>
6.3 配置Map属性注入
<bean name="collectionBean" class="cn.itcast.bean.CollectionBean">
<property name="map">
<map>
<entry key="url" value="jdbc:mysql://localhost:3306/mybatis"></entry>
<entry key="username" value="root"></entry>
<entry key="user" value-ref="user"></entry>
<entry key-ref="user" value-ref="user"></entry>
</map>
</property>
</bean>
6.4 配置Properties属性注入
<bean name="collectionBean" class="cn.itcast.bean.CollectionBean">
<property name="properties">
<props>
<prop key="driverClass">com.jdbc.mysql.Driver</prop>
<prop key="password">root</prop>
</props>
</property>
</bean>
6.5 全部配置
<bean name="collectionBean" class="cn.itcast.bean.CollectionBean">
<property name="arr">
<array>
<value>tom</value>
<value>23</value>
<ref bean="user"/>
</array>
</property>
<property name="list">
<list>
<value>jerry</value>
<value>哈哈</value>
<ref bean="user"/>
</list>
</property>
<property name="map">
<map>
<entry key="url" value="jdbc:mysql://localhost:3306/mybatis"></entry>
<entry key="username" value="root"></entry>
<entry key="user" value-ref="user"></entry>
<entry key-ref="user" value-ref="user"></entry>
</map>
</property>
<property name="properties">
<props>
<prop key="driverClass">com.jdbc.mysql.Driver</prop>
<prop key="password">root</prop>
</props>
</property>
</bean>
输出
CollectionBean [arr=[tom, 23, User [name=p名称空间, age=23, car=null]], list=[jerry, 哈哈, User [name=p名称空间, age=23, car=null]], map={url=jdbc:mysql://localhost:3306/mybatis, username=root, user=User [name=p名称空间, age=23, car=null], User [name=p名称空间, age=23, car=null]=User [name=p名称空间, age=23, car=null]}, properties={driverClass=com.jdbc.mysql.Driver, password=root}]
七、总结
这次我们主要学习了spring的注入方式,多种多样,但是在开发中我们可能用不了那么多,实际情况下我们需要根据实际情况来,毕竟spring也只是一个容器,方便我们的开发而不是复杂我们的开发。