一、概述
(一)Spring框架概念
1.概念:
- Spring框架是一个用于简化Java企业级应用开发的开源应用程序框架。
2.Spring框架的核心与提供的技术支持:
- 核心:
- IoC控制反转|反转控制:利用框架创建类的对象的技术。
- AOP面向切面的编程思想:通过切面类和方法为核心业务提供非核心的业务技术。
- 本身提供了技术支持:
提供了表现层框架:SpringMVC
提供了持久层框架:SpringJDBC
提供了整合其它的三方框架和类库的基础。(Spring框架本身使用Maven框架管理项目)。
3.Spring框架本质:管理项目中的对象(即创建对象和维护对象与对象之间的关系)。
4.Spring的优势
5.Spring的架构
(二)Spring框架的IoC容器
1.IoC
概念:
即控制反转,把创建对象的权利交给框架,即将对象的创建、初始化、存储、管理交给Spring容器。
实质:
一种通过描述来生成或者获取对象的技术。
常用概念:
SpringBean:在Spring中把每一个需要管理的对象称之Spring Bean。
SrpingIoC容器:在Spring中管理这些Bean的容器。
管理过程:
第一步:将需要的POJO提前在配置文件中进行描述(程序员负责)。
第二步:Spring会根据配置文件中的描述生成IoC容器并装配Bean(Spring框架负责)。
第三步:需要该Bean的对象时,通过API获取即可(程序员负责)。
管理过程示意图:
2.耦合与解耦
耦合与解耦
所谓耦合:在项目开发时,经常会遇到在一个程序中会new另外一个类的对象,而在new对象时,会造成当前这个程序,严重的依赖于其它对象,会造成程序之间的依赖程度提升,而程序和程序之间的依赖关系被称之为耦合。依赖关系越高,耦合性就越高。
在项目开发时,我们希望程序和程序之间的耦合程度越低越好。
解耦:解除对象与对象之间的依赖关系就叫解耦。
- 常见的解耦方式
- 1.分层开发解耦方式
- 开发思想:将程序各组成部分定位于不同层次,达到降低耦合度的目的。
- 常见开发模式:工厂模式解耦
- 2.使用框架解耦方式开发思想:IoC和分层开发。
- 1.分层开发解耦方式
二、Maven整合Spring常规开发
(一)开发步骤
第一步:导入Spring依赖
第二步:通过xml文件装配类(Spring的Bean配置)
第三步:读取Bean的配置文件
第四步:通过Api获取Bean
方式一:通过装配类的名字获取bean(源文件中)
方式二:通过类的字节码对象获取bean的对象。
当通过方式二获取Bean对象时,配置文件中不能出现两个不同id值,但class值相同的bean元素。否则会报错。
示例:
(二)ClassPathXmlApplicationContext对象的常用Api。
1.常用API
2.示例:
(三)Bean对象的作用范围
1.概念:
所谓Bean对象的作用范围即作用域,即c|c++的作用域是不同的两个概念。
这里的Bean作用域用于指定创建Bean的创建方式。
2.指定作用范围:
方法:
通过xml配置方式:在bean元素中添加scope属性。
示例:
scope属性的值:
singleton:单实例,默认值。
特点:
Spring容器只为该类创建一个对象,并将该对象存在Bean池中,每次获取都获取的是同一个对象。
该类实例的创建到销毁的全过程由Spring框架管理。
prototype:多实例。
特点:
Spring容器可以为该类创建多个对象中,每次获取时都会重新创建对象。
Spring容器只负责该类的创建,不负责销毁,销毁由JVM的垃圾回收机制负责。
3.作用域的选择:
使用频次维度考虑:
使用频率高的,且没有线程安全的bean:建议使用单例。
原因:始终只有一个实例:可以减少创建时间及获取时间,同时,可以减少内存压力。
使用频次低的,且存在线程安全风险的bean:建议使用多例。
原因:单例Bean总是伴随框架开始而开始,框架结束而结束,占用内存而多例Bean 则不会。
(四)Bean对象的生命周期
1.生命周期概念:
指一个对象何时创建、何时销毁以及创建之后到销毁之前所处的状态。
2.单例Bean对象的生命周期:
创建:当Spring容器对象创建时,此类对象就会被创建。
内存驻留时间:只要容器没有销毁,bean对象就不会销毁。
销毁时机:当Spring容器销毁时,bean对象也会跟前销毁。
3.多例Bean对象的生命周期:
创建时机:当通过IoC对象获取Bean对象时,才会创建Bean对象。
内存驻留时间:只要对象是在使用过程中,则就会一直驻留内存。
销毁时机:当对象长时间不使用,且没有别的对象引用时,则Java垃圾回收机制就会对该对象析构。
4.总结:
单例Bean对象:由Spring全程管理此类对象(即创建、初始化、存储、销毁)。
多例Bean对象:只由Spring负责创建和初始化。不负责存储和销毁(由JVM的CG机制负责)。
5.生命周期方法
初始化方法:
作用:bean对象创建后执行额外的特定的初始化操作,如帮助对象请求各类资源
执行时机:构造函数创建对象后立即执行。
创建方法:使用注解@PostConstruct描述被指定为初始化方法的方法。
示例:
@PostConstruct
public void initObjectPool()
{
System.out.println("initObjectPool()被调用了");
}
适用对象:单例|多例Bean对象。
析构方法:
作用:用于指定销毁Bean对象前额外操作,如释放资源等。
执行时机:Bean对象销毁前。
创建方法:使用注解@PreDestroy描述被指定为析构方法的方法。
示例:
@PreDestroy
public void preDestroyObjectPool()
{
System.out.println("preDestroyObjectPool()被调用了");
}
适用对象:单例Bean对象。
(六)Spring的DI(依赖注入)
1.依赖注入概念:
2.依赖注入方式:
set方法注入:
概念:通过Bean对象的Set方法实现依赖注入。
配置文件方式:修改Bean装配配置文件。
方法:
构造方法注入:
概念:通过Bean对象的构造函数方法实现依赖注入。
配置文件方式:修改Bean装配配置文件。
方法:
三、Spring全注解开发
(一)自定义开发
1.开发步骤
第一步:定义Spring的配置类用于取代bean装配的配置xml文件。
第二步:获取IoC容器对象
第三步:通过IoC容器的API获取所需Bean对象。
可以通过Bean对象所有底层Bean池中的名字,也可以通过Pojo的字节码对象获取
两中方式使用方式和存在的问题与xml方式获取对象时一致。
2.常用注解
@Configuration:
作用:告诉Spring框架当前类是一个Java配置类。
说明:
该注解用于描述类。
此时描述类的具体作用:
所描述类相当于spring的bean.xml(类的装配配置文件)。
通过该类可以获取Spring的IoC容器。
@Bean
作用:将当前方法的返回值作用bean装配到spring容器中。
说明:该注解用于描述方法。所描述的方法与装配的xml文件中的bean元素类似,区别在于:方法中的存入bean池中的对象是new的,而bean元素描述的类的对象是通过框架创建的。
参数name:可选。用于指定bean池中该对象的名字,类似于bean标签中的id属性。
当省略参数时,装配bean到IoC容器中的对象的名字即为@Bean所描述的方法的方法名。
当参数存在时,则对象名即为name的值。
3.使用时机:
如果需要装配第三方技术中的bean时,只能通过自定义开发方式,装配bean对象。
(二)使用Spring扫描装配开发
1.开发步骤
第一步:使用@Component注解描述需要自动装配到IoC容器中的对象所属的Bean。
第二步:使用@ComponentSan注解描述配置类(即使用@Configuration所描述的类)指定扫描的包路径。
第三步:获取IoC容器对象。
第四步:通过IoC对象API获取装配的Bean对象。
示例:
2.常用注解
@Component:
作用:标记所描述的类需要作为bean装配到Spring的IoC容器中。
说明:
参数:
value:可选参数:用于指定存放在Bean池中的名字。
省略时:名字为该注解所描述的类的类名且首字母小写。(默认情况)
存在时:名字为value的值,其中value=可以省略。
@ComponentScan:
作用:定义以何中策略扫描装配Bean
说明:
参数:
value:可选参数:用于指定扫描策略。
省略时:默认扫描当前类所在的包及其子包。
存在时:仅扫描value的值所指定的包,其中value=可以省略。
3.使用时机:
如果需要装配开发者自定义类的对象时,使用Spring扫描的方式装配Bean。
(三)使用注解指定Bean对象的作用域和加载时机
@Scope
作用:用于指定所描述类的对象的作用域。该注解为可选的,无此注解,Spring默认指定当前类的对象的作用域为单实例的。
说明:
参数:
value:可选参数,用于指定该类对象的作用域。
省略或当value值为:singleton时:默认为单例。
示例:@Scope("singleton")|@Scope|@Scope(value="singleton")
当value值为:prototype时:指定所描述类的对象为多例。
示例:@Scope("prototype")|@Scope(value="prototype");
@Lazy
作用:指定所描述的类的加载时机,默认为未延迟加载(即不使用该注解时)。
说明:
参数:
value:可选参数,用于指定Bean对象是否延迟加载。默认值为true。
当为true时,延迟加载。
示例:@Lazy|@Lazy(true)|@Lazy(value=true);
当为false时,不延迟加载。
示例:@Lazy(false)|@Lazy(value=true);
加载时机:
当指定延迟加载时,则会在获取Bean对象时创建。
未指定延迟加载时,则会IoC容器对象创建时就会加载。
前置条件:
该注解只对单例Bean起作用,对多例Bean不起作用。
原因:多例Bean本身即为获取时创建。
使用时机:
针对大型的且使用时机较晚,又需要Spring框架予以装配的单例Bean对象可以使用延迟加载。
(四)使用注解为装配类注入依赖(DI注入)
注解依赖注入规则:
当一个类的属性需要Spring注入依赖的必须条件
该属性所在类必须由Spring管理
该属性必须使用特定注解描述,如:@Vaulue,@Autowired
示例:
@value
作用:使用该注解的实参为所描述的属性赋值。
说明:
该注解用于描述类的属性。
参数:
value:必需参数且无默认值。值为属性赋的值。
示例:
前置条件:
该注解只能为基本数据类型及对应的包装类型和String类的属性赋值。
该注解描述的属性的所属的类必须使用@Component及同等作用的注解描述(@Controller、@Service、@RestController、@Mapper等)
@Autowired
作用:使用该注解为描述的属性赋值。
说明:
该注解描述是类的属性,该属性为自定义类类型。此时将通过暴力反射完成赋值
可以描述类的构造函数。此时,将通过构造方法完成赋值。
可以描述类的某一属性的set就去。此时,将通过set方法完成赋值。
参数:无
前置条件:
该注解只能为开发者自定义类或接口实现类的对象注入依赖。
该注解描述的属性的所属的类必须使用@Component及同等作用的注解描述(@Controller、@Service、@RestController、@Mapper等)
@Autowired依赖注入机制:
首先,会依据类型进入依赖注入,
其次,当IOC容器中该类型的对象有多个时,@Autowired将依据对象名进入依赖注入。
@Autowired注解使用细节(即匹配规则)
前置条件:该属性描述的是接口。
匹配规则:
第一种情况:Bean池中有一个或没有该接口的实现类对象时。
该注解会匹配该接口类型的实现类。
如果没有该接口的实现类,则会报异常如下所示:
如果有该接口的实现类,且只有一个,就会使用该实现类的对象注入@Autowired描述的对象。如下所示:
第二种情况:当Bean中有多个同一接口的实现类时。
该注解首先匹配属性类型,发现Bean池中有多个实现类时,会继续将Bean池中的对象名与属性名进行匹配;
如果未匹配到,则报如下异常:
org.springframework.beans.factory.NoUniqueBeanDefinitionException
如果匹配到,则使用匹配到的Bean对象实现DI注入。如下所示: