第一章:Spring 框架概述
1.1 Spring 框架的定义与背景
Spring 是一个开源的轻量级 Java 开发框架,于 2003 年由 Rod Johnson 创立,旨在解决企业级应用开发的复杂性。其核心设计思想是面向接口编程和松耦合架构,通过分层设计(如表现层、业务层、数据访问层)实现各组件的独立复用,并通过 控制反转(IoC) 和 面向切面编程(AOP) 两大核心技术简化开发流程。
Spring 框架的定位是 Java SE/EE 全栈一站式框架,它不直接替代其他框架(如 MyBatis、Struts 等),而是通过集成机制整合各类技术,降低开发复杂度。
1.2 Spring 框架的核心优点
- 解耦与 IoC 管理
- Spring 作为 “对象工厂”,负责创建和管理对象的生命周期及依赖关系,开发者无需手动创建对象,而是通过配置或注解让 Spring 注入依赖,大幅降低组件耦合度。
- AOP 编程支持
- 通过切面编程,将横切关注点(如日志、事务、权限)与业务逻辑分离,避免代码冗余,提升可维护性。
- 声明式事务管理
- 无需手动编写事务代码,通过注解或配置即可实现事务的提交、回滚,简化数据库操作。
- 便捷的测试支持
- 集成 JUnit 4,通过注解(如
@RunWith(SpringJUnit4ClassRunner.class)
)可直接测试 Spring 管理的组件。
- 集成 JUnit 4,通过注解(如
- 框架集成能力
- 内置对主流框架(如 Hibernate、MyBatis、Spring MVC 等)的支持,通过配置即可完成整合。
- 简化 JavaEE API 调用
- 对复杂的 JavaEE API(如 JDBC、JavaMail)进行封装,提供更简洁的接口,降低使用门槛。
第二章:Spring 的 IoC 核心技术
2.1 什么是 IoC(控制反转)
IoC(Inverse of Control)即 “控制反转”,指将对象的创建、初始化和依赖关系管理从应用代码中剥离,转由 Spring 容器负责。传统开发中,对象的生命周期由代码直接控制(如 new Object()
),而 IoC 框架通过配置或注解 “反转” 了这种控制权,使应用代码仅需关注业务逻辑,无需关心对象创建细节。
2.2 IoC 解决的核心问题:降低程序耦合度
- 传统开发的耦合问题:
若类 A 依赖类 B,则 A 内部需直接创建 B 的实例(如B b = new B();
),此时 A 与 B 强耦合,若 B 的实现类变更,A 的代码也需修改。 - IoC 模式的改进:
通过 Spring 容器配置类 A 对类 B 的依赖,容器在创建 A 时自动注入 B 的实例(如通过构造器或 setter 方法)。此时 A 仅依赖 B 的接口,不关心具体实现,实现了接口与实现的解耦。
2.3 IoC 的实现方式:依赖注入(DI)
IoC 的核心实现机制是 依赖注入(Dependency Injection,DI),即 Spring 容器在创建对象时,将其依赖的组件通过以下方式注入:
- 构造器注入
- 通过类的构造方法传入依赖对象。
- 示例(XML 配置):
<bean id="userService" class="com.example.UserService"><constructor-arg ref="userDao" /> </bean>
- Setter 方法注入
- 通过类的 setter 方法传入依赖对象。
- 示例(注解方式):
@Service public class UserService {private UserDao userDao;@Autowiredpublic void setUserDao(UserDao userDao) {this.userDao = userDao;} }
2.4 IoC 容器的核心接口
- BeanFactory:Spring IoC 容器的基础接口,定义了加载、创建、管理 Bean 的基本功能。
- ApplicationContext:BeanFactory 的子接口,扩展了国际化、事件发布、资源加载等功能,是 Spring 应用中常用的容器接口(如
AnnotationConfigApplicationContext
)。
2.5 IOC的程序入门
创建Java工程,导入坐标依赖
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.0.2.RELEASE</version></dependency><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.12</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope>
</dependency></dependencies>
编写接口和实现类,编写具体的实现方法
packagecom.qcbyjy.service;publicinterfaceUserService{publicvoidhello();}packagecom.qcbyjy.service;publicclassUserServiceImplimplementsUserService{@Overridepublicvoidhello(){System.out.println("HelloIOC!!");}}
编写Spring核心的配置文件,在src目录下创建applicationContext.xml的配置 文件,名称是可以任意的,但是一般都会使用默认名称。
<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!--IOC管理bean--><beanid="userService"class="com.qcbyjy.service.UserServiceImpl"/></beans>
为什么class是impl而不是,userservice?
因为 ioc管理bean ,bean是类。必须要可以实例化才行。
怎么确认他是配置文件的?
通过最顶部的配置信息确认
把log4j.properties的配置文件拷贝到resources目录下,做为log4j的日志配置 文件。 编写测试方法。
packagecom.qcbyjy.test;importcom.qcbyjy.service.UserService;importorg.junit.Test;importorg.springframework.context.ApplicationContext;importorg.springframework.context.support.ClassPathXmlApplicationContext;publicclassDemo1{/***入门程序
*/@Testpublicvoidrun1(){//使用Spring的工厂
ApplicationContextapplicationContext=newClassPathXmlApplicationContext("applicationContext.xml");//通过工厂获得类:UserServiceuserService=(UserService)applicationContext.getBean("userService");userService.hello();}}
2.6 IOC技术总结
ApplicationContext接口,工厂的接口,使用该接口可以获取到具体的Bean对 象。该接口下有两个具体的实现类。springCould配置中心 ClassPathXmlApplicationContext,加载类路径下的Spring配置文件。 FileSystemXmlApplicationContext,加载本地磁盘下的Spring配置文件。
@Testpublic void run0(){ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");UserService userService=context.getBean("userService",UserService.class);userService.hello();}@Testpublic void run1(){ApplicationContext context=new FileSystemXmlApplicationContext("D:\\Spring627\\src\\main\\resources\\applicationContext.xml");UserService userService=context.getBean("userService",UserService.class);userService.hello();}
2.7 Spring框架的Bean管理的配置文件方式
id属性,Bean起个名字,在约束中采用ID的约束,唯一,取值要求:必须以字 母开始,可以使用字母、数字、连字符、下划线、句话、冒号id:不能出现特殊 字符。
class属性,Bean 对象的全路径。
scope属性,scope属性代表Bean 的作用范围。
singleton单例(默认值),最常用的方式。
prototype 多例
request应用在Web项目中,每次HTTP请求都会创建一个新的 Bean
session应用在Web项目中,同一个HTTP Session 共享一个 BeanBean对象的创建和销毁的两个属性配置
说明:Spring初始化 bean 或销毁 bean 时,有时需要作一些处理工作,因此spring可以在创建和拆卸bean 的时候调用 bean 的两个生命周期方法
init-method,当bean 被载入到容器的时候调用 init-method 属性指定的方法destroy-method,当bean 从容器中删除的时候调用 destroy-method 属性指定的方法
<bean id="userService" class="com.qcby.service.UserServiceImpl" scope="prototype" init-method="init" destroy-method="destory"/>
singleton单例
@Testpublic void run2(){ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");UserService userService=context.getBean("userService",UserService.class);UserService userService1=context.getBean("userService",UserService.class);System.out.println(userService);System.out.println(userService1);}
prototype 多例
2.8 实例化Bean对象的三种方式
默认是无参数的构造方法(默认方式,基本上使用)
<bean id="us" class="com.qcbyjy.service.UserServiceImpl" />
静态工厂实例化方式
package com.qcbyjy.demo1;import com.qcbyjy.service.UserService;import com.qcbyjy.service.UserServiceImpl;/*** 静态工厂方式
*/public class StaticFactory {// 静态工厂方式
public static UserService createUs(){System.out.println("通过静态工厂的方式创建UserServiceImpl对
象...");// 编写很多业务逻辑 权限校验
returnnewUserServiceImpl();}}<beanid="us"class="com.qcbyjy.demo1.StaticFactory"factory-method="createUs"/>
实例工厂实例化方式
packagecom.qcbyjy.demo1;importcom.qcbyjy.service.UserService;importcom.qcbyjy.service.UserServiceImpl;/****动态工厂方式
**/publicclassDfactory{publicUserServicecreateUs(){System.out.println("实例化工厂的方式...");returnnewUserServiceImpl();}}<beanid="dfactory"class="com.qcbyjy.demo1.Dfactory"/><beanid="us"factory-bean="dfactory"factory-method="createUs"/>
第三章:DI依赖注入
3.1依赖注入的概述
IOC和DI的概念 IOC:InverseofControl,控制反转,将对象的创建权反转给Spring!! DI:DependencyInjection,依赖注入,在Spring框架负责创建Bean对象时, 动态的将依赖对象注入到Bean组件中!!
3.2属性的set方法注入值
编写属性,提供该属性对应的set方法,编写配置文件完成属性值的注入
packagecom.qcbyjy.service;importcom.qcbyjy.dao.OrderDao;publicclassOrderServiceImplimplementsOrderService{//编写成员属性,一定需要提供该属性的set方法
privateOrderDaoorderDao;//一定需要提供该属性的set方法,IOC容器底层就通过属性的set方法方式注
入值
publicvoidsetOrderDao(OrderDaoorderDao){this.orderDao=orderDao;}//消息
privateStringmsg;//年龄
privateintage;publicvoidsetMsg(Stringmsg){this.msg=msg;}publicvoidsetAge(intage){this.age=age;}@OverridepublicvoidsaveOrder(){System.out.println("业务层:保存订单..."+msg+"-"+age);//调用
orderDao.saveOrder();}}packagecom.qcbyjy.dao;
publicclassOrderDaoImplimplementsOrderDao{@OverridepublicvoidsaveOrder(){System.out.println("持久层:保存订单...");}}<!--DI:依赖注入--><beanid="os"class="com.qcbyjy.service.OrderServiceImpl"><propertyname="orderDao"ref="od"/><propertyname="msg"value="你好"/><propertyname="age"value="30"/></bean><beanid="od"class="com.qcbyjy.dao.OrderDaoImpl"></bean>
3.3 属性构造方法方式注入值
对于类成员变量,构造函数注入。
packagecom.qcbyjy.demo2;publicclassCar{//名称
privateStringcname;//金额
privateDoublemoney;publicCar(Stringcname,Doublemoney){this.cname=cname;this.money=money;}@OverridepublicStringtoString(){return"Car{"+"cname='"+cname+'\''+",money="+money+
'}';}}<beanid="car"class="com.qcbyjy.demo2.Car"><constructor-argname="cname"value="大奔"/><constructor-argname="money"value="400000"/></bean>
3.4 数组,集合(List,Set,Map),Properties 等的注入
packagecom.qcbyjy.demo3;importjava.util.Arrays;importjava.util.List;importjava.util.Map;importjava.util.Properties;publicclassCollectionBean{//数组
privateString[]strs;publicvoidsetStrs(String[]strs){this.strs=strs;}privateList<String>list;publicvoidsetList(List<String>list){this.list=list;}privateMap<String,String>map;publicvoidsetMap(Map<String,String>map){this.map=map;}privatePropertiesproperties;publicvoidsetProperties(Propertiesproperties){this.properties=properties;
}@OverridepublicStringtoString(){return"CollectionBean{"+"strs="+Arrays.toString(strs)+",list="+list+",map="+map+",properties="+properties+'}';}}<!--给集合属性注入值--><beanid="collectionBean"class="com.qcbyjy.demo3.CollectionBean"><propertyname="strs"><array><value>美美</value><value>小凤</value></array></property><propertyname="list"><list><value>熊大</value><value>熊二</value></list></property><propertyname="map"><map><entrykey="aaa"value="老王"/><entrykey="bbb"value="小王"/></map></property><propertyname="properties"><props><propkey="username">root</prop><propkey="password">123456</prop></props></property></bean>
第四章:多配置文件方式
4.1 多配置文件的加载方式
在src的目录下又多创建了一个配置文件,现在是两个核心的配置文件,那么加 载这两个配置文件的方式有两种!
主配置文件中包含其他的配置文件:<importresource="applicationContext2.xml"/>
工厂创建的时候直接加载多个配置文件:ApplicationContextapplicationContext=newClassPathXmlApplicationContext("applicationContext.xml","applicationContext2.xml");