本文是转载文章,文章的来源:csdn博客
博主:李阿昀
转载文章: Spring的概述
转载原文地址:http://blog.csdn.net/yerenyuan_pku/article/details/69663685
转载说明:转载"spring的概述"的后面部分的内容
Spring的bean管理
通俗一点说,Spring的bean管理即指创建对象时不需要new操作代码实现,而是交给Spring进行配置完成。
Spring进行bean管理有两种方式:
- 使用配置文件方式实现
- 使用注解方式实现
本文将重点放在第一种方式上,后一种方式后面会讲。
Spring实例化bean的三种方式
使用无参构造(重点)
创建对象时候,调用类里面的无参数的构造方法实现。那么Spring配置文件中又该怎样写呢?基本类似于如下写法:
<!-- 1.配置user对象的创建 -->
<bean id="user" class="cn.itcast.ioc.User"></bean>
使用静态工厂(了解)
创建一个工厂类,在工厂类中提供一个静态的方法,这个方法返回类的对象;调用工厂类的方法时候,直接使用类名.方法名称
即可以调用。下面举例来说明。
在src目录下创建一个cn.itcast.bean包,并在该包下创建一个Bean1类。
public class Bean1 {
public void bean1() {
System.out.println("bean1..........");
}
}
然后在该包下创建一个Bean1Factory工厂类。
public class Bean1Factory {
// 静态方法
public static Bean1 getBean1() {
return new Bean1();
}
}
接着Spring配置文件中应向下面这样配置:
<!-- 2.使用静态工厂创建对象 -->
<bean id="bean1" class="cn.itcast.bean.Bean1Factory" factory-method="getBean1"></bean>
最后在该包下创建一个TestIOC单元测试类。
public class TestIOC {
@Test
public void demo1() {
// 1.加载Spring配置文件,把配置文件中的对象进行创建
ApplicationContext context =
new ClassPathXmlApplicationContext("bean1.xml");
// 2.根据配置文件的id得到user对象
Bean1 bean1 = (Bean1) context.getBean("bean1");
System.out.println(bean1);
}
}
使用实例工厂(了解)
创建一个工厂类,在工厂类里面提供一个普通的方法,这个方法返回类对象;调用工厂类的方法时候,创建工厂类对象,使用对象调用方法即可。下面也举例来说明。
在src目录下的cn.itcast.bean包下创建一个Bean2类。
public class Bean2 {
public void bean2() {
System.out.println("bean2..........");
}
}
然后在该包下创建一个Bean2Factory工厂类。
public class Bean2Factory {
public Bean2 getBean2() {
return new Bean2();
}
}
接着Spring配置文件中应向下面这样配置:
<!-- 3.使用实例工厂创建对象 -->
<!-- 3.1先创建工厂对象 -->
<bean id="bean2Factory" class="cn.itcast.bean.Bean2Factory"></bean>
<!-- 3.2再使用工厂对象创建bean2对象 -->
<bean id="bean2" factory-bean="bean2Factory" factory-method="getBean2"></bean>
最后将TestIOC单元测试类的代码修改为:
public class TestIOC {
@Test
public void demo1() {
// 1.加载Spring配置文件,把配置文件中的对象进行创建
ApplicationContext context =
new ClassPathXmlApplicationContext("bean1.xml");
// 2.根据配置文件的id得到user对象
Bean2 bean2 = (Bean2) context.getBean("bean2");
System.out.println(bean2);
}
}
Spring配置文件中bean标签常用的属性
Spring配置文件中bean标签常用的属性有以下四种:
- id属性:根据id属性值得到配置对象。
在Spring配置文件中会有多个bean标签,但它们的id属性值是不能相同的。Bean起名字时,在约束中采用的是ID约束——唯一,而且名字必须以字母开始,可以使用字母、数字、连字符、下划线、句号、冒号等,但id属性值不能有特殊符号。 - class属性:要创建对象的类的全路径。
-
scope属性:bean的作用范围。
scope属性共有以下5个属性:-
singleton:创建的对象是单例的,也是scope属性的默认值。
下面我来举例说明它。将TestIOC单元测试类的代码修改为:public class TestIOC { // 得到配置的user对象 @Test public void demo1() { // 1.加载Spring配置文件,把配置文件中的对象进行创建 ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml"); // 2.根据配置文件的id得到user对象 User user1 = (User) context.getBean("user"); User user2 = (User) context.getBean("user"); System.out.println(user1); System.out.println(user2); } }
单元测试以上方法,一切就尽在不言中。其实,此时Spring配置文件中有关如下bean的配置:
<bean id="user" class="cn.itcast.ioc.User"></bean>
就相当于:
<bean id="user" class="cn.itcast.ioc.User" scope="singleton"></bean>
-
prototype:创建的对象是多实例的。
也可举例来说明它。将Spring配置文件中有关如下bean的配置:<bean id="user" class="cn.itcast.ioc.User"></bean>
修改为:
<bean id="user" class="cn.itcast.ioc.User" scope="prototype"></bean>
测试单元测试类的方法就能明白了。
- globalSession:用在单点登录(即SSO,single sign on)上。
-
- name属性:name属性的功能和id属性是一样的。name属性和id属性区别是:在id属性值里面不能有特殊符号,在name属性值里面可以添加特殊符号。
bean的生命周期的配置
通过配置<bean>
标签上的init-method作为bean的初始化的时候执行的方法,配置destroy-method作为bean的销毁的时候执行的方法。销毁方法想要执行,需要是单例创建的Bean而且在工厂关闭的时候,Bean才会被销毁。
Spring中Bean的属性注入
实际上,有关Bean的属性注入共有三种方式,下面我分别加以简单的说明:
-
set方法注入
用代码可表示如下:public class Book { private String bookname; public void setBookname(String bookname) { this.bookname = bookname; } } Book book = new Book(); book.setBookName("Java编程思想");
-
有参数构造注入
用代码可表示如下:public class Book { private String bookname; public Book(String bookname) { this.bookname = bookname; } } Book book = new Book("代码大全");
-
接口注入
先编写一个接口:public interface Dao { public void add(String name); }
再编写这个接口的实现类:
public class DaoImpl implements Dao { private String name; public void add(String name) { this.name = name; } }
但在Spring框架里面,只支持前两种方式,即set方法注入和有参数构造注入。下面我来举例分别演示。
构造方法的方式注入属性
在src目录下创建一个cn.itcast.property包,并在该包下编写一个Book实体类。
public class Book {
private String bookname;
public Book(String bookname) {
this.bookname = bookname;
}
public void testBook() {
System.out.println("book.............." + bookname);
}
}
接着在Spring配置文件中对以上JavaBean添加如下配置:
<!-- 4.使用有参数的构造注入属性 -->
<bean id="book" class="cn.itcast.property.Book">
<!-- 使用标签,name:为属性的名字;value:为属性的值 -->
<constructor-arg name="bookname" value="beautifulMan_美美侠"></constructor-arg>
</bean>
最后在该包下编写一个TestIOC单元测试类:
public class TestIOC {
@Test
public void demo1() {
// 1.加载Spring配置文件,把配置文件中的对象进行创建
ApplicationContext context =
new ClassPathXmlApplicationContext("bean1.xml");
Book book = (Book) context.getBean("book");
book.testBook();
}
}
自己自行测试去吧!
set方法的方式注入属性
我们同样在cn.itcast.property包下编写一个Person实体类,在类中定义属性,并生成set方法。
public class Person {
// 1.定义一个属性
private String username;
// 2.生成这个属性的set方法
public void setUsername(String username) {
this.username = username;
}
public void testperson() {
System.out.println("person.............." + username);
}
}
然后在Spring配置文件中,使用bean标签创建对象,在bean标签里面使用property标签注入属性。即在Spring配置文件中对以上JavaBean添加如下配置,
<!-- 5.使用set方法进行注入属性 -->
<bean id="person" class="cn.itcast.property.Person">
<!--
使用property标签注入属性值
name:类属性名称
value属性:往属性中注入的值
-->
<property name="username" value="李阿昀"></property>
</bean>
最后将TestIOC单元测试类的代码修改为:
public class TestIOC {
@Test
public void demo1() {
// 1.加载Spring配置文件,把配置文件中的对象进行创建
ApplicationContext context =
new ClassPathXmlApplicationContext("bean1.xml");
Person person = (Person)context.getBean("person");
person.testperson();
}
}
自己自行测试去吧!
Spring的属性注入:对象类型的注入
在实际开发中,我们要提交表单到action里面去,然后在action里面调用service层的方法,接着在service层里面调用dao层的方法。在这里,我假设在service层里面调用dao层的方法,所以需要在servcie层里面创建dao层的对象实现调用。
先在src目录下创建一个cn.itcast.dao包,并在该包下编写一个UserDao类。
public class UserDao {
public void add() {
System.out.println("dao................");
}
}
然后在src目录下再创建一个cn.itcast.service包,并在该包下编写一个UserService类。
public class UserService {
public void add() {
System.out.println("service.........");
// 调用dao
balabala......
}
}
如果我们使用最原始的方式在service层里面调用dao层的方法,那么UserService类中add()方法应这样写:
public void add() {
System.out.println("service.........");
// 原始方式,调用dao
UserDao dao = new UserDao();
dao.add();
}
在Spring里面,我们就应该这么玩了。我们的最终目的是在service层里面得到dao层对象。所以步骤为:
-
第一步,让dao作为service的一个属性。
// 1.让dao作为service的一个属性 private UserDao userDao;
-
第二步,生成dao属性的set方法。
// 2.生成dao属性的set方法 public void setUserDao(UserDao userDao) { this.userDao = userDao; }
这时,UserService类的代码就变成:
public class UserService { // 1.让dao作为service的一个属性 private UserDao userDao; // 2.生成dao属性的set方法 public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void add() { System.out.println("service........."); userDao.add(); } }
-
在Spring配置文件中进行配置和注入。
<!-- 6.注入对象的属性 --> <!-- 6.1先创建dao对象 --> <bean id="userDao" class="cn.itcast.dao.UserDao"></bean> <!-- 6.2再创建service对象 --> <bean id="userService" class="cn.itcast.service.UserService"> <!-- 在servcie里面注入userDao属性 name属性:service对象里面的userDao属性的名称 注入dao对象,不能写value属性,要写ref属性:dao配置的bean的id值 --> <property name="userDao" ref="userDao"></property> </bean>
名称空间p的属性注入方式——Spring2.x版本后提供的方式
在src目录下创建一个cn.itcast.propertydemo包,并在该包下编写一个Orders实体类。
public class Orders {
private String oname;
public void setOname(String oname) {
this.oname = oname;
}
public void testorders() {
System.out.println("orders................" + oname);
}
}
接下来我们需要在Spring核心配置文件中的schema约束位置定义p名称空间。
xmlns:p="http://www.springframework.org/schema/p"
紧接着,我们需要在Spring核心配置文件中添加如下配置:
<!-- 7.p(property,属性)名称空间的注入 -->
<bean id="orders" class="cn.itcast.propertydemo.Orders" p:oname="去你妈的!!!"></bean>
最后将cn.itcast.property包下的TestIOC单元测试类的代码修改为:
public class TestIOC {
@Test
public void demo1() {
// 1.加载Spring配置文件,把配置文件中的对象进行创建
ApplicationContext context =
new ClassPathXmlApplicationContext("bean1.xml");
Orders orders = (Orders)context.getBean("orders");
orders.testorders();
}
}
测试即可。
结论——使用p名称空间:
- 普通属性:p:属性名称=”…”
- 对象类型的属性:p:属性名称-ref=”…”
注入复杂属性
注入数组类型的属性
将cn.itcast.propertydemo包下的Orders类的代码修改为:
public class Orders {
private String oname;
public void setOname(String oname) {
this.oname = oname;
}
// 1.数组类型的属性
private String[] arrays;
public void setArrays(String[] arrays) {
this.arrays = arrays;
}
public void testorders() {
// System.out.println("orders................" + oname);
System.out.println("数组:" + Arrays.toString(arrays));
}
}
然后需要在Spring核心配置文件中添加如下配置:
<bean id="orders" class="cn.itcast.propertydemo.Orders"> <!-- 创建对象 -->
<!-- 数组类型 -->
<property name="arrays"> <!-- 注入属性 -->
<list>
<value>叶子</value>
<value>liayun</value>
<value>杰哥</value>
</list>
</property>
</bean>
最后将cn.itcast.property包下的TestIOC单元测试类的代码修改为:
public class TestIOC {
@Test
public void demo1() {
// 1.加载Spring配置文件,把配置文件中的对象进行创建
ApplicationContext context =
new ClassPathXmlApplicationContext("bean1.xml");
Orders orders = (Orders)context.getBean("orders");
orders.testorders();
}
}
测试即可。
注入List集合类型的属性
将cn.itcast.propertydemo包下的Orders类的代码修改为:
public class Orders {
private String oname;
public void setOname(String oname) {
this.oname = oname;
}
// 2.list类型的属性
private List<String> list;
public void setList(List<String> list) {
this.list = list;
}
public void testorders() {
// System.out.println("orders................" + oname);
System.out.println("list:" + list);
}
}
然后需要在Spring核心配置文件中添加如下配置:
<bean id="orders" class="cn.itcast.propertydemo.Orders"> <!-- 创建对象 -->
<!-- list类型 -->
<property name="list">
<list>
<value>叶子</value>
<value>李昀玲</value>
<value>杰哥</value>
</list>
</property>
</bean>
cn.itcast.property包下的TestIOC单元测试类的代码勿须修改,直接测试即可。
注入Set集合类型的属性
将cn.itcast.propertydemo包下的Orders类的代码修改为:
public class Orders {
private String oname;
public void setOname(String oname) {
this.oname = oname;
}
// 3.set类型的属性
private Set<String> keyset;
public void setKeyset(Set<String> keyset) {
this.keyset = keyset;
}
public void testorders() {
// System.out.println("orders................" + oname);
System.out.println("set:" + keyset);
}
}
然后需要在Spring核心配置文件中添加如下配置:
<bean id="orders" class="cn.itcast.propertydemo.Orders"> <!-- 创建对象 -->
<!-- set类型 -->
<property name="keyset">
<set>
<value>蝙蝠侠</value>
<value>钢铁侠</value>
<value>美美侠</value>
</set>
</property>
</bean>
其实,以上配置也可以写为:
<bean id="orders" class="cn.itcast.propertydemo.Orders"> <!-- 创建对象 -->
<!-- set类型 -->
<property name="keyset">
<list>
<value>蝙蝠侠</value>
<value>钢铁侠</value>
<value>美美侠</value>
</list>
</property>
</bean>
cn.itcast.property包下的TestIOC单元测试类的代码勿须修改,直接测试即可。
注入Map集合类型的属性
将cn.itcast.propertydemo包下的Orders类的代码修改为:
public class Orders {
private String oname;
public void setOname(String oname) {
this.oname = oname;
}
// 4.map类型
private Map<String, String> map;
public void setMap(Map<String, String> map) {
this.map = map;
}
public void testorders() {
// System.out.println("orders................" + oname);
System.out.println("map:" + map);
}
}
然后需要在Spring核心配置文件中添加如下配置:
<bean id="orders" class="cn.itcast.propertydemo.Orders"> <!-- 创建对象 -->
<!-- map类型 -->
<property name="map">
<map>
<entry key="username" value="潘金莲"></entry>
<entry key="password" value="1314"></entry>
<entry key="address" value="明初"></entry>
</map>
</property>
</bean>
cn.itcast.property包下的TestIOC单元测试类的代码勿须修改,直接测试即可。
注入Properties类型的属性
将cn.itcast.propertydemo包下的Orders类的代码修改为:
public class Orders {
private String oname;
public void setOname(String oname) {
this.oname = oname;
}
// 5.properties
private Properties properties;
public void setProperties(Properties properties) {
this.properties = properties;
}
public void testorders() {
// System.out.println("orders................" + oname);
System.out.println("properties:" + properties);
}
}
然后需要在Spring核心配置文件中添加如下配置:
<bean id="orders" class="cn.itcast.propertydemo.Orders"> <!-- 创建对象 -->
<!-- properties类型 -->
<property name="properties">
<props>
<prop key="name">宫本一郎</prop>
<prop key="address">日本</prop>
</props>
</property>
</bean>
cn.itcast.property包下的TestIOC单元测试类的代码勿须修改,直接测试即可。
IoC和DI的区别
- IoC:控制反转,即把对象的创建交给Spring进行管理。所以Spring IoC容器是用来创建对象,管理依赖关系的。
- DI(Dependency Injection):依赖注入,即在创建对象的过程中,向类里面的属性中设置值。
- IoC和DI的关系:依赖注入不能单独存在,须在控制反转基础之上完成,用更通俗点的话来说,就是注入类里面的属性值,不能直接注入,须创建类的对象再完成注入。
Spring中的工厂
ApplicationContext
ApplicationContext接口有两个实现类,如下图:
- ClassPathXmlApplicationContext:加载的是类路径下的Spring配置文件
- FileSystemXmlApplicationContext:加载的是本地磁盘下的Spring配置文件
BeanFactory
下面应该是BeanFactory类的继承体系图吧!
稍微了解一下就好,这个类在实际开发中我们并不需要用到。
ApplicationContext和BeanFactory的区别
虽然使用这两个对象都可以加载Spring的配置文件,并创建配置文件中的对象。但他俩还是有区别的,最主要的区别是:
- 使用applicationContext操作时,可把Spring里面的配置文件中的对象都进行创建。
- 使用BeanFactory对象操作时,在调用getBean方法的时候进行对象的创建。
Spring整合Web项目的底层原理
在实际的开发中,我们一般会使用SSH(即Struts2、Spring、Hibernate)进行开发,然后创建Spring的配置文件,使用applicationContext对象加载配置文件,继而创建对象。在真正的开发中,我们一般不会直接写applicationContext代码加载配置文件。
Spring整合Web项目的思想
在服务器启动的时候,加载Spring配置文件,并创建对象。
Spring整合Web项目的底层原理
Spring整合Web项目用到以下两个技术:
- 使用ServletContext对象(在服务器启动时创建)
- 使用监听器
在服务器启动的时候,每个项目都会创建一个ServletContext对象,而且每个项目只有一个ServletContext对象。在ServletContext对象创建的时候,使用监听器可以监听到其创建。当我们监听到ServletContext对象创建时,Spring就会帮我们做一件事情——加载Spring配置文件,并把配置文件中的对象进行创建,对象创建之后,放到ServletContext域里面去,最终我们要使用创建的对象,可从ServletContext域里面获取出来。