1.Spring 介绍
1.1 Spring 概述
Spring 是一个开源框架,Spring 是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作 Expert One-On-One J2EE Development and Design 中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。Spring 使用基本的 JavaBean 来完成以前只可能由 EJB 完成的事情。然而,Spring 的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何 Java 应用都可以从 Spring 中受益。简单来说,Spring 是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
1.2 Spring 好处
-
方便解耦,简化开发
- Spring 就是一个大工厂,专门负责生成 Bean,可以将所有对象创建和依赖关系维护由 Spring 管理。通过 Spring 提供的 IoC 容器,可以将对象间的依赖关系交由 Spring 进行控制,避免硬编码所造成的过度程序耦合。用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。
-
AOP 变成的支持
- Spring 提供面向切面编程,可以方便的实现对程序进行权限拦截,运行监控等功能。通过 Spring 的 AOP 功能,方便进行面向切面的编程,许多不容易用传统 OOP 实现的功能可以通过 AOP 轻松应付。
-
声明式事务的支持
- 只需要通过配置就可以完成对事务的管理,而无需手动编程
-
方便程序的测试
- Spring 对 Junit4 支持,可以通过注解方便的测试 Spring 程序
-
方便集成各种优秀框架
- Spring 不排斥各种优秀的开源框架,其内部提供了对各种优秀框架的支持,如 Struts、Hibernate、Mybatis、Quartz 等
-
降低 JavaEE API 的使用难度
- 对 JavaEE 开发中一些难用的 API(JDBC、JavaMail、远程调用等),都提供了封装,使这些 API 应用难度大大降低
-
Java 源码是经典学习范例
- Spring 的源代码设计精妙、结构清晰、匠心独用,处处体现着大师对 Java 设计模式灵活运用以及对 Java 技术的高深造诣。它的源代码无意是 Java 技术的最佳实践的范例。
1.3 Spring 结构体系
Spring 框架是一个分层架构,它包含一系列的功能要素并被分为大约 20 个模块。这些模块分为 Core Container、DataAccess/Integration、Web、AOP、Instrumentation 和测试部分。如下图所示:
1.4 在项目中的架构
- web 层:Struts,SpringMVC
- dao 层:Hibernate,Mybatis
1.5 程序的耦合和解耦
-
程序的耦合
- 我们开发种,会写很多的类,而有些类之间不可避免地产生依赖关系,这种依赖关系称为耦合。有些依赖是必须的,有些依赖关系可以通过优化代码来解除。比如:
/**
* 客户的业务层实现类
*/
public class CustomerServiceImpl implements ICustomerService {private ICustomerDao customerDao = new CustomerDaoImpl();
}
- 上面的代码表示:业务调用持久层,并且此时业务再依赖持久层的接口和实现类。如果此时没有持久层实现类,编译将不能通过。这种依赖关系就是我们可以通过优化代码解决的。
- 再比如:下面的代码种,我们的类依赖 MySQL 的具体驱动类,如果这狮虎更换了数据库品牌,我们需要改源码来修修改数据库驱动,这显然不是我们想要的。
public class JdbcDemo1 {
/**
* JDBC 操作数据库的基本入门中存在什么问题?* 导致驱动注册两次是个问题,但不是严重的。* 严重的问题:是当前类和 mysql 的驱动类有很强的依赖关系。* 当我们没有驱动类的时候,连编译都不让。* 那这种依赖关系,就叫做程序的耦合
*
* 我们在开发中,理想的状态应该是:* 我们应该尽力达到的:编译时不依赖,运行时才依赖。*
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
//1. 注册驱动
//DriverManager.registerDriver(new com.mysql.jdbc.Driver());
Class.forName("com.mysql.jdbc.Driver");
//2. 获取连接
//3. 获取预处理 sql 语句对象
//4. 获取结果集
//5. 遍历结果集
}
-
解决程序耦合的思路
-
在 JDBC 种是通过反射来注册驱动的,代码如下:
Clas.forName("com.mysql.jdbc.Driver");
- 这时的好处是,我们类中不再依赖具体的驱动类,此时就算删除 MySQL 的驱动 jar 包,依然可以编译。但是没有驱动类,所以不能运行。
- 不过,此处也有一个问题,就是我们反射类对象的全限定类名字符串是在 Java 类中写死的,一旦要改还是徐娅修改源码。为了解决这个问题,使用配置文件配置。
-
-
工厂模式解耦
- 在实际开发过程总我们把所有的 dao 和 service 和 action 对象使用配置文件配置起来,当启动服务器应用加载的时候,通过读取配置文件,把这些对象创建出来并存起来。在接下来使用的时候,直接拿就好了。
-
控制反转 —Inversion Of Control
-
上面解耦的思路有两个问题
- 创建的对象存储在哪里?由于我们是很多对象,肯定要找个集合来存储,这时候有 Map 和 List 供选择。到底是选择 Map 还是 List 就看我们有没有查找的需求。有查找的需求就选 Map。所以我们的答案是:在应用加载时,创建一个 Map,用于存放 action,service 和 dao 对象。
- 还是没解释什么是工厂? 工厂就是负责给我们从容器中获取指定对象的类。这时候获取对象的方式发生了改变。以前,我们在获取对象的时候,都是采用 new 的方式,是主动的。
-
- 现在,我么获取对象的时候,同时跟工厂要,有工厂为我们查找或者创建对象。是被动的。这种被动接收的方式获取对象的思想就是控制反转,他是 Spring 框架的核心之一。其作用只有一个:降低计算机程序的耦合。
2. Spring 快速入门
- 使用 spring 的 IOC 解决程序耦合
2.1 编写流程
- 下载 Spring 开发包
- 导入 Spring 的 jar 包
- 配置 Spring 的核心 xml 文件
- 在程序中读取 Spring 的配置文件来获取 Bean【Bean 其实就是一个 new 好的对象】
2.2 下载地址
- 这里下载 4.2.4 版本
- 地址:http://repo.spring.io/release…
- 官网:spring.io 官网改版后,下载链接需要在对应的 GitHub 上找
2.3 Spring 的核心 jar 包
- spring-core-4.2.4.RELEASE.jar 包含 Spring 框架基本的核心工具类,Spring 其他组件都要使用到这个包里得嘞,是其他组件的基本核心。
-
spring-beans-4.2.4.RELEASE.jar 所有应用都要用到的,它包含访问配置文件、创建和管理 bean
以及进行 Inversion of Control(IoC) / Dependency Injection(DI) 操作相关的所有类。
-
spring-context-4.2.4.RELEASE.jarSpring 提供在基础 IoC 功能上的扩展服务,此外还提供许多企业级服务的支持,
如邮件服务、任务调度、JNDI 定位、EJB 集成、远程访问、缓存以及各种视图层框架的封装等。
- spring-expression-4.2.4.RELEASE.jarSpring 表达式语言。
- com.springsource.org.apache.commons.logging-1.1.1.jar 第三方的主要用于处理日志。
2.4 Spring 入门案例
-
准备项目需要得 jar 包
- spring-framework-4.2.4.RELEASE-dist.zip【Spring 的核心包】
- spring-framework-4.2.4.RELEASE-dependencies.zip【Spring 的依赖包】
- 创建 Project,导入 Spring 的 jar 包
-
在 src 路径下创建 applicationContext.xml 文件
- 导入约束
- 把资源交给 Spring 管理,在 xml 文件中配置 User
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 约束的位置在:
..\spring-framework-4.2.4.RELEASE\docs\spring-framework-reference\html\xsd-configuration.html
文档末尾 -->
<!--
1. 基本配置:bean 标签:指定要创建的实体类
id 属性:可以为任意值 但是在整个配置文件中唯一
class 属性:要实例化类的全限定名 反射
-->
<bean id="user" class="com.itzhouq.domain.User"></bean>
</beans>
-
测试
package com.itzhouq.domain; public class User {public void run() {System.out.println("run"); } }
package com.itzhouq.test; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.itzhouq.domain.User; public class UserTeset { @Test public void test() {// 自己 new 的对象 User user = new User(); user.run();} @Test public void test2() {//spring 的 ioc 创建对象 // 加载配置文件 src/classes 类路径 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); // 找 Spring 要对象 User user = (User) context.getBean("user"); user.run();} }
3. Spring 基于 XML 的 IOC 细节
3.1 IOC 中 bean 标签和管理对象细节
3.1.1 配置文件 bean 标签
-
作用
- 用于配置对象让 Spring 来创建的。默认情况下它调用的是类中的无参构造函数。如果没有无参构造函数则不能创建成功。
-
属性
- id:给对象在容器中提供一个唯一标识,用于获取对象
- class:指定类的全限定名。用于反射创建对象,默认情况下调用无参构造函数。
- scope:指定对象的作用范围。
- init-method:指定类中的初始化方法名称。
- destroy-method: 指定类中销毁方法名称。
- import:导入外部配置文件,resource—- 外部配置文件的地址。
3.1.2 scope 属性:范围(重点)
<bean id="user" class="cn.itzhouq.domain.User" scope="singleton" ></bean>
- singleton: 单实例 默认值
- 如果是单实例, 配置文件文件只要一加载 就会创建对象 放在 spring 容器 (map<id, 对象 >)
- 当所有人过来问 spring 容器要的时候 (getBean), 所用人用的都是同一个对象
-
prototype: 多实例
- 如果是多实例, 配置文件加载, 不创建对象
- 当每个人过来 getbean 的时候,getbean 一次创建一次 放在容器中
-
什么时候用默认值 singleton(单实例)? 什么时候用 prototype(多实例)?
- action: prototype
- service/dao: singleton
- request:web 项目中 Spring 创建一个 Bean 对象,将对象存入到 request 域中
- session:web 项目中 Spring 创建一个 Bean 对象,将对象存入到 session 域中。
- globalSession:web 项目中,应用在 Portlet 环境,如果没有 Portlet 环境那么 globalSession 相当于 session。
3.1.3 bean 的作用范围和生命周期
-
单例对象:scope=”singleton”
- 一个应用只有一个对象的实例。它的作用范围就是整个引用。
-
生命周期:
- 对象出生:当应用加载,创建容器时,对象就被创建了。
- 对象活着:只要容器在,对象一直活着。
- 对象死亡:当应用卸载,销毁容器时,对象就被销毁了。
- 多例对象:scope=”prototype”
- 每次访问对象时,都会重新创建对象实例。
-
生命周期:
- 对象出生:当使用对象时,创建新的对象实例。
- 对象活着:只要对象在使用中,就一直活着。
- 对象死亡:当对象长时间不用时,被 java 的垃圾回收器回收了。
3.1.4 示例化 Bean 的三种方式
-
无参构造方式(最常用)
@Test// 测试 bean 的三种创建方式 ------ 无参构造方式 public void test3() { // 加载配置文件 src/classes 类路径 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); // 找 Spring 要对象 User user = (User) context.getBean("user"); user.run();}
-
静态工厂方式(了解)
-
条件:需要有一个工厂类,在这个工厂类中还需要一个静态方法
package com.itzhouq.utils; import com.itzhouq.domain.User; public class BeanFactory {public static User createUser() {return new User(); } }
<!-- 静态工厂方式 --> <bean id="user" class="com.itzhouq.utils.BeanFactory" factory-method ="createUser">
-
测试
@Test// 测试 bean 的三种创建方式 ------ 静态工厂方式 public void test4() {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); User user1 = (User) context.getBean("user"); System.out.println(user1);//com.itzhouq.domain.User@5f3a4b84 User user2 = (User) context.getBean("user"); System.out.println(user2);//com.itzhouq.domain.User@5f3a4b84 }
-
-
实例工厂方式(了解)
- 条件:需要一个工厂类在这个工厂类中需要一个普通方法
package com.itzhouq.utils; import com.itzhouq.domain.User; public class BeanFactory {// public static User createUser() {// return new User(); // } // 普通方法 ---- 实例工厂 public User createUser() {return new User(); } }
-
配置文件
<!-- 实例工厂 --> <bean id="beanFactory" class="com.itzhouq.utils.BeanFactory"></bean> <bean id="user" factory-bean="beanFactory" factory-method="createUser"></bean>
-
测试
@Test// 测试 bean 的三种创建方式 ------ 实例工厂方式 public void test5() {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); User user1 = (User) context.getBean("user"); System.out.println(user1);//com.itzhouq.domain.User@5f3a4b84 User user2 = (User) context.getBean("user"); System.out.println(user2);//com.itzhouq.domain.User@5f3a4b84 }
3.2 加载 Spring 容器的三种方式
- 类路径获得配置文件
- 文件系统路径获得配置文件
- 使用 BeanFactory(了解)
public class Lession01 {
@Test
public void test01(){
//Spring 容器加载有 3 种方式
// 第一种:ClassPathXmlApplicationContext ClassPath 类路径加载:指的就是 classes 路径
// 最常用,Spring 的配置文件以后就放在 src 路径下
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
// 第二种方式:文件系统路径获得配置文件【绝对路径】ApplicationContext context = new FileSystemXmlApplicationContext("E:\\workspaces\\IdeaProject\\Spring-day02-gyf\\src\\beans.xml");
IUserService user = (IUserService) context.getBean("userService");
user.add();
// 第三种方式:String path = "E:\\workspaces\\IdeaProject\\Spring-day02-gyf\\src\\beans.xml";
BeanFactory factory = new XmlBeanFactory(new FileSystemResource(path));
IUserService user1 = (IUserService) factory.getBean("userService");
user1.add();}
}
-
Spring 内部创建对象的原理
1. 解析 xml 文件,获得类名,id,属性 2. 通过反射,用类型创建对象 3. 给创建的对象赋值
3.3 BeanFactory 和 ApplicationContext 对比
- BeanFactory 采用延迟加载,第一次 getBean 时才会初始化 Bean
-
ApplicationContext 是对 BeanFactory 扩展,提供了更多功能
- 国际化处理
- 事件传递
- Bean 自动装配
- 各种不同应用的 Context 实现
3. 4 Spring 的依赖注入 DI
- DI 属性的依赖注入,是 Spring 框架核心 IoC 的具体实现方式。Spring 在通过 Ioc 创建对象的时候,如果这个对象还有属性,就一并赋值进去,而不用我们自己去获取。
-
入门举例:
-
创建一个接口 Car
package com.itzhouq.service; public interface Car {public void run(); }
-
创建实现类 CarImpl
package com.itzhouq.serviceImpl; import com.itzhouq.service.Car; public class CarImpl implements Car { private String name; public void setName(String name) {this.name = name;} @Override public void run() {System.out.println(name+"车跑起来了....."); } }
-
测试
package com.itzhouq.test; import org.junit.Test; import com.itzhouq.serviceImpl.CarImpl; public class CarTest { @Test// 自己 new 对象 自己属性赋值的方式 public void test() {CarImpl car = new CarImpl(); car.setName("qq"); car.run();//qq 车跑起来了.....} }
-
-
入门举例 2:依赖注入的方式
-
配置文件:
<!-- DI:属性的依赖注入 --> <bean id="car" class="com.itzhouq.serviceImpl.CarImpl"> <!-- property:是 set 属性的方式 name:要赋值的属性名 value:要赋的值 --> <property name="name" value="兰博基尼"></property> </bean>
-
测试
@Test //Spring 的 IOC public void test2() {ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml"); Car car = (Car)context.getBean("car"); // 把这个对象的属性也在创建的时候给顺便赋值了 -----DI car.run();// 兰博基尼车跑起来了.....}
-
-
依赖注入的方式
- 构造函数注入(了解)
- set 方法注入(掌握)
- 使用 p 名称空间注入数据(本质还是调用 set 方法)(了解)
- 注入集合属性
3.4.1 构造器注入方式
- 条件:需要有有参构造方法
-
给 CarImpl 设置有参构造
package com.itzhouq.serviceImpl; import com.itzhouq.service.Car; public class CarImpl implements Car { private String name; private double price; public void setName(String name) {this.name = name;} public double getPrice() {return price;} public void setPrice(double price) {this.price = price;} public String getName() {return name;} public CarImpl() {} // 有参的构造方法 ----DI 的构造器注入方式 public CarImpl(String name, double price) {super(); this.name = name; this.price = price; } @Override public void run() {System.out.println("价值"+price+"的"+name+"车跑起来了....."); } }
-
配置文件
<!-- DI 的注入方式, 构造器注入方式 name: 要赋值的属性名 value:要赋的值(针对的是基本数据类型和 String 类型)ref 针对的是对象类型 --> <bean id="car" class="com.itzhouq.serviceImpl.CarImpl"> <constructor-arg name="name" value="BMW"></constructor-arg> <constructor-arg name="price" value="1000000"></constructor-arg> </bean>
-
测试
@Test //Spring 的 DI 注入方式 ---- 构造器的注入方式(了解)public void test3() {ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml"); Car car = (Car)context.getBean("car"); car.run();// 价值 1000000.0 的 BMW 车跑起来了.....}
3.4.2 set 方式注入
-
写一个 Person 接口
package com.itzhouq.service; public interface Person {}
-
PersonImpl 实现接口 Person, 设置 set 方法
package com.itzhouq.serviceImpl; import com.itzhouq.service.Car; import com.itzhouq.service.Person; public class PersonImpl implements Person { private String name; private Car car; public String getName() {return name;} public void setName(String name) {this.name = name;} public Car getCar() {return car;} public void setCar(Car car) {this.car = car;} @Override public String toString() {return "PersonImpl [name=" + name + ", car=" + car + "]"; } }
-
配置文件
<bean id="car" class="com.itzhouq.serviceImpl.CarImpl"> <constructor-arg name="name" value="BMW"></constructor-arg> <constructor-arg name="price" value="1000000"></constructor-arg> </bean> <!-- DI 的注入方式,set 注入方式 name: 要赋值的属性名 value:要赋的值(针对的是基本数据类型和 String 类型)ref 针对的是对象类型, 指的是 Spring 中 bean 的 id 名 --> <bean id="person" class="com.itzhouq.serviceImpl.PersonImpl"> <property name="name" value="jack"></property> <property name="car" ref="car"></property> </bean>
-
测试
@Test //Spring 的 DI 注入方式 ----set 的注入方式(了解)public void test4() {ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml"); Person person = (Person) context.getBean("person"); System.out.println(person); //PersonImpl [name=jack, car=CarImpl [name=BMW, price=1000000.0]] }
3.4.3 使用 p 名称空间注入数据 (知道就 OK)
- 此种方式是通过在 xml 中导入 p 名称空间,使用 p:propertyName 来注入数据,它的本质仍然是调用类中的 set 方法实现注入功能。
-
配置文件
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="customerService" class="com.itheima.service.impl.CustomerServiceImpl4" p:name="test" p:age="21" p:birthday-ref="now"/> </beans>
3.4.4 注入集合属性
- 顾名思义,就是给类中的集合成员传值,它用的也是 set 方法注入的方式,只不过变量的数据类型都是集合。我们这里介绍注入数组,List,Set,Map,Properties。
-
创建一个类 CollBean,设置 set 方法
package com.itzhouq.domain; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Properties; public class CollBean {private String[] ss; private List ll; private Map mm; private Properties properties; public String[] getSs() {return ss;} public void setSs(String[] ss) {this.ss = ss;} public List getLl() {return ll;} public void setLl(List ll) {this.ll = ll;} public Map getMm() {return mm;} public void setMm(Map mm) {this.mm = mm;} public Properties getProperties() {return properties;} public void setProperties(Properties properties) {this.properties = properties;} @Override public String toString() {return "CollBean [ss=" + Arrays.toString(ss) + ", ll=" + ll + ", mm=" + mm + ", properties=" + properties + "]"; } }
-
配置文件
<bean id="car" class="com.itzhouq.serviceImpl.CarImpl"> <constructor-arg name="name" value="BMW"></constructor-arg> <constructor-arg name="price" value="1000000"></constructor-arg> </bean> <!-- DI 复杂属性注入 --> <bean id="collBean" class="com.itzhouq.domain.CollBean"> <property name="ss"> <!-- 数组类型 --> <list> <value>aaa</value> <value>bbb</value> <value>ccc</value> </list> </property> <property name="ll"> <!-- 集合类型 --> <list> <value>111</value> <value>222</value> <ref bean="car"></ref> </list> </property> <property name="mm"> <!-- map 类型 --> <map> <entry key="k1" value="AAA"></entry> <entry key="k2" value="BBB"></entry> <entry key="k3" value-ref="car"></entry> </map> </property> <property name="properties"> <!-- properties --> <props> <prop key="hibernate.username">root</prop> <prop key="hibernate.password">1234</prop> </props> </property> </bean>
- 测试
package com.itzhouq.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.itzhouq.domain.CollBean;
public class CollBeanTest {
@Test
public void test() {ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
CollBean cb = (CollBean) context.getBean("collBean");
System.out.println(cb);
/*
* CollBean [ss=[aaa, bbb, ccc],
* ll=[111, 222, CarImpl [name=BMW, price=1000000.0]],
* mm={k1=AAA, k2=BBB, k3=CarImpl [name=BMW, price=1000000.0]},
* properties={hibernate.password=1234, hibernate.username=root}]
*/
}
}
4. 使用案例
- 需求分析:从 service 层调用 dao 层,将数据存储到数据库,存储数据的过程使用 syso 模拟一下就可以。
- 创建工程,导入需要的 jar 包,建包如下:
-
创建 dao 层和 dao 实现层
package com.itzhouq.dao; public interface UserDao {void save(); }
package com.itzhouq.daoImpl; import com.itzhouq.dao.UserDao; public class UserDaoImpl implements UserDao{ @Override public void save() {System.out.println("操作数据库,保存用户的数据"); } }
-
创建 Service 层和实现层
package com.itzhouq.service; public interface UserService {public void save(); }
package com.itzhouq.serviceImpl; import com.itzhouq.dao.UserDao; import com.itzhouq.daoImpl.UserDaoImpl; import com.itzhouq.service.UserService; public class UserServiceImpl implements UserService { private String name; private UserDao userDao; public void setUserDao(UserDao userDao) {this.userDao = userDao;} public void setName(String name) {this.name = name;} @Override public void save() {System.out.println(name); // 调用 dao userDao.save();} }
- 给 UserDaoImpl 一个 UserDao 属性
-
配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 创建 dao --> <bean id="userDao" class="com.itzhouq.daoImpl.UserDaoImpl"></bean> <!-- 创建 service --> <bean id="UserService" class="com.itzhouq.serviceImpl.UserServiceImpl"> <property name="name" value="要开始访问 dao 了"></property> <property name="userDao" ref="userDao"></property> </bean> </beans>
-
测试
@Test // 使用 Spring 的 IOC+DI 来实现对象的创建和赋值 public void test() {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService = (UserService) context.getBean("UserService"); userService.save(); // 要开始访问 dao 了 // 操作数据库,保存用户的数据 }