现在的位置: 首页 > 综合 > 正文

Java回顾之Spring基础Java回顾之集合

2012年08月18日 ⁄ 综合 ⁄ 共 6970字 ⁄ 字号 评论关闭

  第一篇:Java回顾之I/O

  第二篇:Java回顾之网络通信

  第三篇:Java回顾之多线程

  第四篇:Java回顾之多线程同步

  第五篇:Java回顾之集合

  第六篇:Java回顾之序列化

  第七篇:Java回顾之反射

  第八篇:Java回顾之一些基础概念

  第九篇:Java回顾之JDBC

  第十篇:Java回顾之ORM框架

 

  我计划分两到三篇文章来描述Spring,这一篇主要讲Spring一些基础的内容。

  概述

  我印象4、5年前,我还做java开发的时候,Spring是一个非常火的框架,尤其是在Web开发领域,和Struts以及Hibernate构成了SSH三剑客。当时Web开发的另一个组合是LAMP,即Linux+Apache+MySQL+PHP。我在前端方面基本没有实战经验,对js等技术也还是停留在概念和语法方面,所以扬长避短,我对Spring以及Hibernate特别感兴趣。

  当年Spring是作为EJB的“替代者”横空出世的,其创始人Rod Johnson还写了一本《J2EE development without EJB》来推行这个框架,这也是一本关于Spring很经典的书,不过最好是在接触Spring一段时间后再去阅读,效果会好一点。

  Spring最主要的特点有两个:IoC和AOP,这也是J2EE开发企业软件时经常碰到的问题:1)对象太多如何管理;2)共同逻辑和业务逻辑纠缠在一起,错综复杂,如何解耦。

  这篇文章主要关注3个方面:IoC、AOP和数据库访问。这里我们假设所有需要的jar都已经准备就绪。

  IoC

  IoC的全称是Inversion of Control,中文称为控制反转, Martin Flower由根据它创造了一个新词:Dependency Injection,中文称为依赖注入。这两个词讲的是一回事儿。

  IoC的实质是如何管理对象,传统意义上我们使用new方式来创建对象,但在企业应用开发的过程中,大量的对象创建都在程序中维护很容易造成资源浪费,并且不利于程序的扩展。

  实现IoC通常有三种方式:

  1)利用接口或者继承,一般以接口较多。这种实现方式和我们平时提到的lazy load有异曲同工之妙。

  2)构造函数注入。

  3)属性注入。

   IoC是Spring框架的核心,接下来我们来探索一下Spring中IoC的风采。

  IoC简单示例

  我们先来定义一个简单的接口和实现:

 1 public interface UserDao {
 2     void save();
 3 }
 4 
 5 public class UserDaoImpl implements UserDao
 6 {
 7 
 8     public void save() {
 9         System.out.println("save() is called.");
10     }
11 
12 }

  然后是在classpath下创建一个beans.xml文件(这个文件名不是必须这样的):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
                http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

    <bean id="userDaoImpl" class = "sample.spring.ioc.UserDaoImpl"/>
</beans>    

  接下来是测试代码:

1 private static void test1()
2 {
3     ApplicationContext ctx = new ClassPathXmlApplicationContext("sample/spring/ioc/beans.xml");
4     UserDao userDao = (UserDao)ctx.getBean("userDaoImpl");
5     userDao.save();
6 }

  输出结果如下:

save() is called.

  我们还可以通过工厂方式来创建对象。

  通过静态工厂创建Bean

  添加一个类,如下:

1 public class UserDaoFactory {
2 
3     public static UserDao getUserDao()
4     {
5         return new UserDaoImpl();
6     }
7 }

  在beans.xml中,添加如下内容:

1 <bean id="userDaoImpl2" class = "sample.spring.ioc.UserDaoFactory" factory-method = "getUserDao"/>

  测试代码和执行结果和上面类似,不再赘述。

  通过实例工厂创建Bean

  添加如下类:

1 public class UserDaoFactory2 
2 {
3     public UserDao getUserDao()
4     {
5         return new UserDaoImpl();
6     }
7 }

  这个类和UserDaoFactory唯一的区别是这里的getUserDao是实例方法,而不是静态方法。

  在beans.xml中追加如下内容:

1 <bean id="factory" class="sample.spring.ioc.UserDaoFactory2"/>
2 <bean id="userDaoImpl3" factory-bean="factory" factory-method="getUserDao"/>

  测试方法和结果同上。

  对象的生命周期

  我们可以通过设置bean节点的scope属性来控制对象的声明周期,它包含两个可选值:

  1)singleton,表明系统中对于同一个对象,只保留一个实例。

  2)prototype,表明系统中每次获取bean时,都新建一个对象。

  我们修改beans.xml文件:

1 <bean id="userDaoImpl" class = "sample.spring.ioc.UserDaoImpl" scope="singleton"/>
2 <bean id="userDaoImpl2" class = "sample.spring.ioc.UserDaoImpl" scope="prototype"/>

  这两个bean指向同一个类型,但是scope的设置不同。

  下面是测试方法:

 1 private static void scopeTest()
 2 {
 3     ApplicationContext ctx = new ClassPathXmlApplicationContext("sample/spring/ioc/scope.xml");
 4     System.out.println("=====Singleton test=====");
 5     UserDao userDao1A = (UserDao)ctx.getBean("userDaoImpl");
 6     UserDao userDao1B = (UserDao)ctx.getBean("userDaoImpl");
 7     System.out.println("userDao1A == userDao1B:" + (userDao1A==userDao1B));
 8     System.out.println("=====Prototype test=====");
 9     UserDao userDao2A = (UserDao)ctx.getBean("userDaoImpl2");
10     UserDao userDao2B = (UserDao)ctx.getBean("userDaoImpl2");
11     System.out.println("userDao2A == userDao2B:" + (userDao2A==userDao2B));
12 }

  执行结果如下:

=====Singleton test=====
userDao1A == userDao1B:true
=====Prototype test=====
userDao2A == userDao2B:false

  如何设置对象属性

  上面的示例中,我们的对象中没有包含属性,对于业务对象来说,这一般是不现实。实际中的对象或多或少都会有一些属性。

  Spring支持两种方式对属性赋值:set方式和构造函数。

  下面我们会分别描述两种方式,但首先我们需要展示业务对象:

 1 public class UserServiceBean 
 2 {
 3     private int userID;
 4     private String userName;
 5     private UserDao userDao;
 6     private List<String> hobbies;
 7     private Map<String, Integer> scores;
 8     
 9     public UserServiceBean(int userID, String userName, UserDao userDao, List hobbies,Map scores)
10     {
11         this.userID = userID;
12         this.userName = userName;
13         this.userDao = userDao;
14         this.hobbies = hobbies;
15         this.scores = scores;
16     }
17     
18     public UserServiceBean(){}
19     
20     public void setUserID(int userID) {
21         this.userID = userID;
22     }
23     public int getUserID() {
24         return userID;
25     }
26     public void setUserName(String userName) {
27         this.userName = userName;
28     }
29     public String getUserName() {
30         return userName;
31     }
32     public void setUserDao(UserDao userDao) {
33         this.userDao = userDao;
34     }
35     public UserDao getUserDao() {
36         return userDao;
37     }
38     public void setHobbies(List<String> hobbies) {
39         this.hobbies = hobbies;
40     }
41     public List<String> getHobbies() {
42         return hobbies;
43     }
44     public void setScores(Map<String, Integer> scores) {
45         this.scores = scores;
46     }
47     public Map<String, Integer> getScores() {
48         return scores;
49     }
50 }

定义UserServiceBean

  这是一个典型的学生信息,包括学号、姓名、爱好和成绩。

  通过Set方式为对象属性赋值

  我们在beans.xml中追加如内容:

 1 <bean id="userService" class="sample.spring.ioc.UserServiceBean">
 2     <property name="userID" value="1"/>
 3     <property name="userName" value="张三"/>
 4     <property name="userDao" ref="userDaoImpl"/>
 5     <property name="hobbies">
 6         <list>
 7             <value>羽毛球</value>
 8             <value>看电影</value>
 9             <value>弹吉他</value>
10         </list>
11     </property>
12     <property name="scores">
13         <map>
14             <entry key="数据结构" value="90"/>
15             <entry key="编译原理" value="85"/>
16             <entry key="离散数学" value="82"/>
17         </map>
18     </property>
19 </bean>

  上面是典型的为属性赋值的示例,其中属性不仅包括简单属性(整数、字符串),也包含了复杂属性(List、Map),还有其他的bean。

  下面是测试代码:

 1 private static void propertyTest1()
 2 {
 3     ApplicationContext ctx = new ClassPathXmlApplicationContext("sample/spring/ioc/beans.xml");
 4     UserServiceBean userService = (UserServiceBean)ctx.getBean("userService");
 5     printUserService(userService);
 6 }
 7 
 8 private static void printUserService(UserServiceBean userService)
 9 {
10     System.out.println("编号:" + userService.getUserID());
11     System.out.println("姓名:" + userService.getUserName());
12     System.out.println("爱好:");
13     for(String hobby:userService.getHobbies())
14     {
15         System.out.println(hobby);
16     }
17     System.out.println("学习成绩:");
18     for(Entry<String,Integer> entry:userService.getScores().entrySet())
19     {
20         System.out.println(entry.getKey() + "\t" + entry.getValue());
21     }
22     userService.getUserDao().save();
23 }

  输出结果如下:

编号:1
姓名:张三
爱好:
羽毛球
看电影
弹吉他
学习成绩:
数据结构    90
编译原理    85
离散数学    82
save() is called.

  通过构造函数为对象属性赋值

  我们也可以通过构造函数来为对象赋值,在上面定义UserServiceBean时,我们已经添加了一个构造函数。下面来看beans.xml中的配置:

 1 <bean id="userService2" class="sample.spring.ioc.UserServiceBean">
 2     <constructor-arg index="0" value="1"/>
 3     <constructor-arg index="1" value="张三"/>
 4     <constructor-arg index="2" ref="userDaoImpl"/>
 5     <constructor-arg index="3">
 6         <list>
 7             <value>羽毛球</value>
 8             <value>看电影</value>
 9             <value>弹吉他</value>
10         </list>
11     </constructor-arg>
12     <constructor-arg index="4">
13         <map>
14             <entry key="数据结构" value="90"/>
15             <entry key="编译原理" value="85"/>
16             <entry key="离散数学" value="82"/>
17         </map>
18     </constructor-arg>
19 </bean>

  测试代码和输出结果同上。

  需要注意:我们定义的业务对象应该保留默认的构造函数。

  使用Annotation来定位Bean

  在Spring中,除了在xml配置文件中定义对象,我们还可以使用Annotation来定位,这位我们提供了很大的方便。

  这里我们使用的Annotation主要包括:@Resource/@Autowried/@Qualifier。

  来看下面的示例:

 1 public class UserServiceBean2
2 {
3 private

抱歉!评论已关闭.