目录
第一节 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管理。 - AOP编程的支持:
Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能。 - 声明式事务的支持:
只需要通过配置就可以完成对事务的管理,而无需手动编程。 - 方便程序的测试:
Spring对Junit4支持,可以通过注解方便的测试Spring程序。 - 方便集成各种优秀框架:
Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibernate、MyBatis、Quartz等)的支持。 - 降低JavaEE API的使用难度:
Spring对JavaEE开发中一些难用的API(JDBC、JavaMail、远程调用webservice等),都提供了封装,使这些API应用难度大大降低。
1.3 Spring体系结构
- Spring 框架是一个分层架构,它包含一系列的功能要素并被分为大约20个模块。这些模块分为Core Container、Data Access/Integration、Web、AOP(Aspect Oriented Programming)、Instrumentation和测试部分,如下图所示:
1.4 Spring在项目中的架构
- Web层:Struts,SpringMVC
- Service层:Spring
- Dao层:Hibernate,Mybatis
第二节 Spring快速入门
2.1 下载Spring的开发包
- 官网的是最新的版本,4版本之前的不好找到
Spring官网: https://spring.io/projects/spring-framework#learn.
- 这里是Spring3.2以上版本的下载地址:
Spring下载地址:https://repo.spring.io/libs-release-local/org/springframework/spring/.
2.2 Spring的核心jar包
- spring-core-3.2.2.RELEASE.jar
包含Spring框架基本的核心工具类,Spring其它组件要都要使用到这个包里的类,是其它组件的基本核心。 - spring-beans-3.2.2.RELEASE.jar
所有应用都要用到的,它包含访问配置文件、创建和管理bean以及进行Inversion of Control(IOC) / Dependency Injection(DI)操作相关的所有类。 - spring-context-3.2.2.RELEASE.jar
Spring提供在基础IOC功能上的扩展服务,此外还提供许多企业级服务的支持,如邮件服务、任务调度、JNDI定位、EJB集成、远程访问、缓存以及各种视图层框架的封装等。 - spring-expression-3.2.2.RELEASE.jar
Spring表达式语言 - com.springsource.org.apache.commons.logging-1.1.1.jar
第三方的jar包,主要用于处理日志。
2.3 Spring的入门案例
第一步:创建项目,导入相关jar包
- spring-framework-3.2.0.RELEASE-dist.zip 【Spring的核心包】
- spring-framework-3.0.2.RELEASE-dependencies.zip 【Spring的依赖包】
- 在依赖包中找到处理日志的jar包:com.springsource.org.apache.commons.logging-1.1.1.jar
- 在核心包中找到其它jar包,并创建一个文件夹,存入
导入4核心(beans、core、context、expression) + 1个依赖(common-logging.jar)
注意导入时,不要导入带sources的源文件了
- 创建一个spring项目
- 这里不选择下载
- 选择自己配置的jar
第二步:写一个简单的Service,并使用
- UserService接口
package com.it.service;
public interface UserService {
public void add();
}
- UserServiceImpl并实现UserService接口
package com.it.service;
public class UserServiceImpl implements UserService{
@Override
public void add() {
System.out.println("添加用户...");
}
}
- 简单测试一下,感受一下之前是怎么使用Service的
package com.it.test;
import com.it.service.UserServiceImpl;
import com.it.service.UserService;
import org.junit.Test;
public class demo01 {
@Test
public void test1(){
//以前使用Service,自己创建对象
UserService userService = new UserServiceImpl();
userService.add();
}
}
第三步:Spring IOC控制反转创建实例
- 在src下写个配置文件beans.xml,配置文件的约束可以在spring-framework-3.2.0.RC2-docs/reference/html/xsd-config.html中查看
- 有dtd约束也有xsd约束
- 将下面的约束复制粘贴进beans.xml中
- xsd初始配置
<?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">
<!-- bean definitions here -->
</beans>
- 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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--配置一个bean【对象】-->
<!--写接口的实现类,不能写接口-->
<bean class="com.it.service.UserServiceImpl" id="userService"></bean>
</beans>
第四步:从beans.xml中获取bean
//IOC控制反转实例
@Test
public void test2(){
//以前使用Service,自己创建对象
/*UserService userService = new UserServiceImpl();
userService.add();*/
//现在使用Service,从spring容器中取
//1.加载spring配置文件 beans.xml ,spring容器内部就会创建对象
//ClassPathXml表示从src下取
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//2.从spring容器获取 userService对象(getBean根据id获取bean)
UserService userService1 = (UserService) context.getBean("userService");
userService1.add();
UserService userService2 = (UserService) context.getBean("userService");
userService2.add();
//验证userService1和2是否是同一个
System.out.println(userService1);
System.out.println(userService2);
}
IOC总结
- IOC(Inverse of Control )反转控制,就是将原本在程序中手动创建UserService对象的控制权,交由Spring框架管理。简单的说,就是创建UserService对象控制权被反转到了Spring框架。
2.4 DI(依赖注入)
- (DI)Dependency Injection 依赖注入,在Spring框架创建Bean对象时,动态的将依赖对象注入到Bean组件中。
依赖注入案例
- 在UserServiceImpl中提供一个get/set的name方法
- 此时如果不在beans.xml注入一个name值,执行test2,默认调用name的空参构造
- 在beans.xml中通过property去注入一个name值
- 再次运行test2
- 如果不提供set方法会报错
- 依赖注入是调用属性的set方法给属性赋值
第三节 加载Spring容器的三种方式
第一种方式:类路径获得配置文件【最常用】
- 以后就把spring配置文件beans.xml放在src目录下即可
@Test
public void test1(){
//spring容器加载的三种方式
//第一种:类路径获取配置文件 ClassPathXmlApplicationContext
//如果在包路径下,要写包名 例如:beans.xml在com.it.service包下要写成:com/it/service/beans.xml
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
UserService userService = (UserService) context.getBean("userService");
userService.add();
}
第二种方式:文件系统路径获得配置文件
@Test
public void test2(){
//spring容器加载的三种方式
//第二种:文件系统路径获得配置文件 FileSystemXmlApplicationContext
//拷贝beans.xml的绝对路径,粘贴进去
ApplicationContext context = new FileSystemXmlApplicationContext("D:\\Spring\\src\\beans.xml");
UserService userService = (UserService) context.getBean("userService");
userService.add();
}
第三种方式:使用BeanFactory【了解】
@Test
public void test3(){
//spring容器加载的三种方式
//第三种:使用BeanFactory 【这种方法已过时】
String path = "D:\\Spring\\src\\beans.xml";
BeanFactory factory = new XmlBeanFactory(new FileSystemResource(path));
UserService userService = (UserService) factory.getBean("userService");
userService.add();
}
spring内部创建对象的原理:
1.解析xml文件,获取类名,id,属性
2.通过反射,用类型创建对象
3.给创建的对象赋值
BeanFactory和ApplicationContext对比
-
在UserServiceImpl中添加一个空参构造打印一句话
-
BeanFactory采取延迟加载(懒加载),第一次getBean时才会初始化Bean
-
ApplicationContext采取即时加载
-
ApplicationContext是对BeanFactory扩展,提供了更多功能
- 国际化处理
- 事件传递
- Bean自动装配
- 各种不同应用层的Context实现
第四节 装配Bean(xml)的三种方式
- 所谓装配bean就是在xml中写一个bean标签。
第一种方式:通过new 实现类
第二种方式:通过静态工厂方法
- 之前使用静态工厂
- 通过bean使用静态工厂
- 由于spring版本低的问题(这里使用的是spring3.2)报错
- 降低jdk版本为1.7,即可解决
调用2次UserServiceImpl的原因:在beans1.xml中配置了2个bean,ApplicationContext是即时加载,都会加载进容器。
第三种方式:通过实例工厂方法
- 所谓的实例就是要调用对象,不是调用类方法了。
- 先复制UserServiceFactory改名为UserServiceFactory1,并去掉里面的static
- 通过bean使用实例工厂
第五节 bean的作用域
类别 | 说明 |
singleton(常用) | 在Spring IoC容器中仅存在一个Bean实例,Bean以单例方式存在,默认值 |
prototype(常用) | 每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时 ,相当于执行new XxxBean() |
request | 每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境 |
session | 同一个HTTP Session 共享一个Bean,不同Session使用不同Bean,仅适用于WebApplicationContext 环境 |
globalSession | 一般用于Portlet应用环境,该作用域仅适用于WebApplicationContext 环境 |
singleton 单例【默认值】
- 默认单列,且里面只有一个bean,每次获取都是同一个对象,地址值相同
prototype 多例
第六节 bean的生命周期【了解】
生命周期图
生命周期图解释
- instantiate:bean对象实例化
- populate properties:封装属性
- 如果Bean实现BeanNameAware:执行 setBeanName
- 如果Bean实现BeanFactoryAware:执行setBeanFactory ,获取Spring容器
- 如果存在类实现 BeanPostProcessor(后处理Bean) ,执行postProcessBeforeInitialization
- 如果Bean实现InitializingBean:执行 afterPropertiesSet
- 调用<bean init-method=“init”> 指定初始化方法 init
- 如果存在类实现 BeanPostProcessor(处理Bean) ,执行postProcessAfterInitialization执行业务处理
- 如果Bean实现 DisposableBean 执行 destroy
- 调用<bean destroy-method=“customerDestroy”> 指定销毁方法 customerDestroy
bean的生命周期演示
- User.java
package com.it.model;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
/**
* @ClassName User
* @Author shuyy
* @Date 2020/9/9 19:42
**/
public class User implements BeanNameAware, BeanFactoryAware, InitializingBean, DisposableBean {
private String username;
private String password;
public User() {
System.out.println("1.构造方法实例化...");
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
System.out.println("2.设置属性username:"+username);
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
System.out.println("2.设置属性password:"+password);
this.password = password;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
@Override
public void setBeanName(String s) {
System.out.println("3.设置bean的名字:"+s);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
//把对象放进工厂(就是把对象放进一个容器中)
System.out.println("4.bean工厂:"+beanFactory);
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("6.属性赋值完成...");
}
public void myInit(){
System.out.println("7.自定义的初始化方法...");
}
@Override
public void destroy() throws Exception {
//资源释放
System.out.println("9.bean被销毁了...");
}
public void myDestroy(){
//资源释放
System.out.println("10.自定义的销毁方法...");
}
}
- MyBeanPostProcessor.java
package com.it.model;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
* @ClassName MyBeanPostProcessor
* @Author shuyy
* @Date 2020/9/9
**/
//bean处理器,需要注册给Spring容器,统一处理所有的bean,只需要注册
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
//后处理:在初始化前
//这里可以用于多个对象共同处理的事
System.out.println("5.预处理:"+o+":"+s);
return o;
}
@Override
public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
//后处理:在初始化后
System.out.println("8.后处理:"+o+":"+s);
return o;
}
}
- beans3.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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--bean的生命周期--><!--7.设置自定义初始化方法 myInit--><!--10.设置自定义销毁方法 myDestroy-->
<bean class="com.it.model.User" id="user" init-method="myInit" destroy-method="myDestroy">
<!--2.设置属性-->
<property name="username" value="shu"></property>
<property name="password" value="123"></property>
</bean>
<!--5、8配置bean处理器(无需配置id)-->
<bean class="com.it.model.MyBeanPostProcessor"></bean>
</beans>
- demo5.java
package com.it.test;
import com.it.model.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/*
* @Author ShuYY
* @Description bean的生命周期
* @Date 19:34 2020/9/9
* @Param
* @return
**/
public class demo05 {
@Test
public void test1() throws Exception {
//bean的生命周期
ApplicationContext context = new ClassPathXmlApplicationContext("beans3.xml");
User user = (User) context.getBean("user");
System.out.println(user);
//手动关闭容器后,9.destroy销毁方法才会执行
context.getClass().getMethod("close").invoke(context);
}
}
- 效果: