1、系统架构
包含核心模块:
- 核心容器(Core Container)
Spring的核心模块,其他的都需要依赖该模块 - AOP
面向切面编程,它依赖核心层容器,目的是“在不改变原有代码的前提下对其进行功能增强”
Aspects:AOP是思想,Aspects是对AOP思想的具体实现 - 数据层
开发与整合
1)Data Access:数据访问
2)Data Integration:数据继承,支持整合其他的数据层解决方案 - 事务管理
3)Transactions:事务 - 表现层开发与整合
web层:SpringMVC框架
Test层:整合Junit完成单元测试和集成测试
Spring框架的主要功能:
用来管理对象,基于对象管理的前提下,对管理的对象进行功能的增强
2、核心概念
1、IoC什么意思?
使用对象时由 开发者使用new 创建对象 转换为由 外部提供对象,这种思想成为控制反转(IoC)
2、Spring和IoC的关系是什么?
Spring对IoC思想进行实现
Spring提供容器称为IoC容器,充当IoC思想中的外部。
3、Ioc容器作用以及内部存放什么?
- Ioc容器负责对象的创建、初始化等一系列工作,其中包含数据层和业务层的类对象
- 被创建或被管理的对象在Ioc容器中统称为Bean
- Ioc容器中存放Bean对象
4、Ioc中创建好Service和dao对象后就能执行了吗?
不行,service运行需要依赖dao对象,此时这个关系的建立用到DI。
5、DI是什么意思?
在Spring的IoC容器中,根据要求,建立bean与bean之间的依赖关系的过程成为依赖注入DI
入门案例
都没有new对象
<!--id属性在同一个上下文(配置文件)中不能重复
bean标签表示配置bean
id属性表示给bean起名字
class属性表示给bean定义类型 某种程度上,Dao在哪需要被创建,class就定位到哪-->
<bean id = "bookDao" class = "com.endorphin.dao.Impl.BookDaoImpl"/>
<bean id = "bookService" class = "com.endorphin.service.Impl.BookServiceImpl">
<!--DI依赖注入
配置service与dao的关系
property标签表示配置当前bean的属性
name属性表示配置哪一个具体的属性 对象的类型
ref属性表示参照哪一个bean bean的id-->
<property name = "bookDao" ref = "bookDao"/>
</bean>
//BookServiceImpl类
public class BookServiceImpl implement BookService{
//private BookDao bookDao = new BookDaoImpl()
//删除业务层中使用new方式创建的dao对象
private BookDao bookDao;
@override
//....
//提供对应的set方法因为没有new对象
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
}
//主方法 没有用DI
psvm{
//获取IoC容器
ApplicationContext ctx = new ClassPathXmlAllicationContext("applictionContext.xml");
//bean对象
BookService bookservice = ()ctx.getBean("bookService");
bookservice.save();
}
3、IoC相关内容
1、Spring创建的对象默认是单例对象。如果想修改成非单例对象,通过scope属性进行“prototype”
2、封装属性的实体类是否需要配置成bean?
由于实体类用于封装属性,每个实体类对象保存的数据均不相同,不适合交给Spring容器管理,因此不建议配置成bean
bean基础配置
class属性不能写接口的全类名,因为接口不能创建对象
- 什么bean默认为单例?
- bean为单例的意思是在Spring的IOC容器中只会有该类的一个对象
- bean对象只有一个就避免了对象的频繁创建与销毁,达到了bean对象的复用,性能高
- bean在容器中是单例的,会不会产生线程安全问题?
- 如果对象是有状态对象,即该对象有成员变量可以用来存储数据的,
- 因为所有请求线程共用一个bean对象,所以会存在线程安全问题。
- 如果对象是无状态对象,即该对象没有成员变量没有进行数据存储的,
- 因方法中的局部变量在方法调用完成后就会被销毁,所以不会存在线程安全问题。
- 哪些bean对象适合交给容器进行管理?
- 表现层对象
- 业务层对象
- 数据层对象
- 工具对象
- 哪些bean对象不适合交给容器进行管理?
- 封装实例的域对象,因为会引发线程安全问题,所以不适合。
- 可以在不同Servlet之间传递数据的对象,就是域对象。只要是域对象都有如下方法:
setAttribute(name,value);存储数据的方法
getAttribute(name);根据name获取对应数据值
removeAttribute(name);删除数据
bean别名配置
name为bean指定别名,别名可以有多个,使用逗号、分号、空格进行分隔
bean作用范围配置
scope为bean设置作用范围,可选值为单例singloton,非单例prototype
getBean中根据bean标签的id属性和name属性的任意一个值来获取bean对象
获取bean无论是通过id还是name获取,如果无法获取到,将抛出异常NoSuchBeanDefinitionException
为什么bean默认为单例?
- bean为单例的意思是在Spring的IoC容器中只会有该类的一个对象
- bean对象只有一个就避免了对象的频繁创建与销毁,达到了bean对象的复用,性能高
bean在容器中是单例的,会不会产生线程安全问题?
如果对象是有状态对象,即该对象有成员变量可以用来存储数据,因为所有请求线程共用一个bean对象,所以会存在线程安全问题。
如果对象时无状态对象,即该对象没有成员变量、没有进行数据存储,因为方法中的局部变量在方法调用完成后就会被销毁,所以不会存在线程安全问题。
4、bean实例化
以上只说明对象已经能交给Spring的IoC容器创建了,并没有指明容器是如何创建对象的。
构造方法实例化
通过一系列实验证明,Spring底层采用反射、类的无参构造方法。构造方法在类中默认会提供,如果重写了构造方法,默认的就会消失,最好也重写默认的构造方法。
静态工厂初始化(了解)
实例工厂与FactoryBean
实例工厂类中的方法不是静态方法,还需要在xml中配置bean,用FactoryBean来简化开发。
//创建一个UserDaoFactoryBean的类,实现FactoryBean接口,重写接口的方法
public class UserDaoFactoryBean implements FactoryBean<UserDao> {
//代替原始实例工厂中创建对象的方法
public UserDao getObject() throws Exception {
return new UserDaoImpl();
}
//返回所创建类的Class对象
public Class<?> getObjectType() {
return UserDao.class;
}
}
实现FactoryBean接口,提供泛型类型,泛型类型即当前FactoryBean创建的对象类型。
Spring的FactoryBean接口其实有三个方法,还有一个是设置对象是否Wie单例,默认true。
5、bean的生命周期
bean的生命周期是bean对象从创建到销毁的整体过程。bean的生命周期控制的是在bean创建后到销毁前做一些事情。
bean初始化对应的代码执行,bean销毁前对应的代码未执行,原因:
Spring的IOC容器是运行在JVM中,运行main方法后,JVM启动,Spring加载配置文件生成IOC容器,从容器中获取bean对象然后调用方法执行,main方法执行完后,JVM退出,这时候IOC容器中的bean还没有来得及销毁就已经结束了,所以没有调用对应的destroy方法。
解决办法:
1、close关闭容器。由于ApplicationContext中没有close方法,需要将ApplicationContext更换为ClassPathXmlApplicationContext。
2、注册钩子关闭容器
在容器未关闭之前,提前设置好回调函数,让虚拟机在退出之前回调此函数来关闭容器。调用ctx的registerShutdownHook()方法.
6、DI相关内容(两种注入方式)
setter注入
注入引用数据类型:在bookServiceImpl对象中引入UserDao
在类中声明属性、提供set方法,在xml中提供property即可。
注入简单数据类型
在类中声明对应的简单数据类型的属性,并提供对应的setter方法。xml中写property标签
构造器注入(了解)
添加带参数的构造方法,xml中添加标签constructor-arg
7、自动配置
什么是依赖自动装配
IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配。
自动装配方式有哪些
按类型、按名称、按构造方法、不启用自动装配
在xml中删除property标签,在bean中添加autowire属性。autowire属性开启自动装配,通常使用按类型装配。
注意:
- 需要注入属性的类中对应属性的setter方法不能省略
- 被注入的对象必须要被Spring的IOC容器管理
- 按照类型在Spring的IOC容器中如果找到多个对象,会报错。