spring 基础
spring 基础
ruoxijunSpring 入门
框架:对高通用性可重用代码进行高质量抽取的一种设计,形成多个可重用的模块集合后而组成对某个领域整体的解决方案。
框架编程流程:导包、编写配置、测试、编写业务。
Spring 简介:
- Spring 是一个开源免费,轻量级,非入侵式的框架
- 重点核心:控制反转( IOC ),面向切面编程( AOP )
- 支持事务的处理,对其他框架整合支持
- 弊端 :配置十分繁琐,人称 “配置地狱”
Spring组成:
Spring 框架是一个分层架构,由 7 个定义良好的模块组成。
添加 Spring 依赖:
由上可知Spring分为许多模块,在使用Spring时我们选择导入 spring-webmvc
依赖。此包中包含了多数我们需要使用的模块。
1 | <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> |
IOC(控制反转):
IOC:Inversion Of Control 控制反转
控制反转将对象的创建交给了IOC容器,IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对象的创建。
Spring在初始化时先读取配置文件,根据配置文件创建对象并存入IOC容器,根据使用再从IOC容器中取出需要的对象,即获取对象的方式反转了。
简单入门实例:
1. 定义两个类:
1 | //使用了 lombok 注解快速生成了必要方法 |
1 |
|
2. 在 resources 文件夹中创将 Bean 配置文件:
在 resources 文件夹下创建 applicationContext.xml
(推荐命名,也可以自定义命名)文件,此文件也称之为 bean 文件因为其内部的一个bean
标签就表示一个对象。
1 |
|
3. 编写测试类:
spring 中有一个接口 ApplicationContext 它就代表 IOC 容器接口,它的实现类可以帮我们来获取对象。
xml 配置对象(bean),可以通过 ClassPathXmlApplicationContext 类来获取。它会获取resources文件夹下指定的xml配置文件,所以传入参数时请以resources为根目录传入bean文件的完整路径名。
1 | /** |
测试结果:
1 | Hello(str=property, hi=Hi(str=World)) |
4. import 关联配置文件:
此外我们在了解一下bean文件导入。如我们将入门案例中bean的 hi1
与 hi2
对象(标签)移到新建名为**hi.xml
的bean文件中再回到applicationContext.xml
添加如下配置引入hi.xml
。不改变其它内容你会发现程序一切正常,这说明我们将hi.xml
中的bean成功引入到了applicationContext.xml
**中:
1 | <!-- import:导入其他的bean文件,resource:文件的相对路径 |
DI(依赖注入,反射赋值):
DI:Dependency Injection 依赖注入
1.构造器注入:
使用有参构造器创建对象则需要在 bean 中需要使用 constructor-arg
标签,根据属性不同分为三种方式。
- 利用下标:
1 | <bean id="hello" class="io.github.ruoxijun.pojo.Hello" name="Hello"> |
- 利用类型:
1 | <bean id="hello" class="io.github.ruoxijun.pojo.Hello" name="Hello"> |
- 利用参数名称(常用):
1 | <bean id="hello" class="io.github.ruoxijun.pojo.Hello" name="Hello"> |
- 了解直接赋值,此方式需严格按照构造器参数顺序赋值:
1 | <bean id="hello" class="io.github.ruoxijun.pojo.Hello" name="Hello"> |
对于重载的构造器需要可能需要使用多个属性来进行指定赋值,最方便的方式就是通过 name 属性赋值。
2. Set 注入(重点):
之前我们已经学过了两种类型的Set注入:
1 | <bean id="address" class="io.github.ruoxijun.pojo.Address"> |
其它类型的Set注入( 除字符串和基本类型以外其它所有的复杂类型都在 property 标签内进行 ):
1 | <bean id="user" class="io.github.ruoxijun.pojo.User"> |
3. p 命名和 c 命名空间注入:
p和c命名空间实则就是对 property
和 constructor-arg
标签的简化使用,同时它们的作用还能防止出现标签重复。
- p命名空间属性注入:
要使用p命名空间注入需要在bean文件的头标签(beans)中添加如下属性值(IDEA中可自动生成):
1 | xmlns:p="http://www.springframework.org/schema/p" |
之前注入是利用property
对应的name和values属性:
1 | <bean id="address" class="io.github.ruoxijun.pojo.Address"> |
开启p命名空间后bean中会多出一种p属性,“:”后面跟上此类中可set注入的属性名进行赋值:
1 | <bean id="address" class="io.github.ruoxijun.pojo.Address" p:address="value" p:**="***"/> |
- c命名空间构造器注入:
同理需要在bean文件的头标签(beans)中添加开启c命名空间注入的属性值:
1 | xmlns:c="http://www.springframework.org/schema/c" |
使用同理:
1 | <bean id="address" class="io.github.ruoxijun.pojo.Address" c:address="value"/> |
bean 作用域:
之前 getBean
同一个 bean 时拿到的是同一个对象 ,这是因为 bean作用域 问题。bean的 scope 属性默认值为 singleton 也就是 单例模式 ,所有我们拿到的对象始终是同一个的原因。
1 | <bean id="hi" class="io.github.ruoxijun.pojo.Hi" scope="singleton"/> |
我们通过改变scope属性值来改变bean的作用域,它的值有一下几种:
1 | singleton // 单例模式,Spring默认模式(容器启动完成之前创建对象存入容器) |
Spring与工厂模式:
- 工厂模式:创建一个类的实例需要配置许多繁杂的属性时,我们可以通过工厂模式来完成类的创建并通过工厂的方法来获取该类的实例。在工厂类中对每个实例做了默认配置,我们只需修改我们需要的属性即可。
- 静态工厂:不用创建工厂本身对象,通过静态方法调用获取对象实例
- 对象=工厂类.获取实例静态方法名();
- 动态工厂:需要创建工厂本身对象,调用工厂方法获取对象实例
- 工厂类对象=new 工厂类(); 对象=工厂类对象.获取实例方法名();
1. 静态工厂:
1 | <!-- 静态工厂: |
2. 动态工厂:
1 | <!-- 动态工厂(实例工厂) |
3. FactoryBean:
Spring中实现了 FactoryBean接口 的类spring会自动识别为工厂类,spring会自动调用工厂方法创建实例。 FactoryBean泛型 为你需要创建的对象
1 | // FactoryBean<AirPlane> 中的泛型为你需要此工厂类为你创建实例的类型 |
最终在使用时该bean会自动调用 getObject 方法获取实例对象。
1 | <bean id="factoryBean" class="ruoxijun.pojo.AirPlaneFactoryBean"/> |
注意该类 isSingleton 无论是否单例都只会在获取该bean时(getBean)才会 创建实例对象 。
创建带生命周期方法的bean:
- 在类中定义两个要作为生命周期的方法,方法名和返回值都可以随意,但此方法 参数必须为空 。
1 | // 在构造方法之后执行 |
- 配置bean并指定初始和销毁方法
1 | <!-- init-method:指定初始化时的方法 |
Spring 后置处理器:
spring中实现 BeanPostProcessor 接口的类并注册为bean后被自动识别为后置处理器。该类的两个监控方法会在Spring初始化每一个bean时调用。
1 | public class MyBeanPostProcessor implements BeanPostProcessor { |
bean 生命周期总结:
构造器
→ 后置处理器before
→ init-method(初始化方法)
→ 初始化完成
→ 后置处理器after
→ (容器关闭)destroy-method(销毁方法)
自动装配(autowire):
有如下三个类:
1 |
|
在bean文件中进行配置:
1 | <bean id="cat" class="ruoxijun.pojo.Cat" p:name="猫"/> |
bean中提供了一种属性 autowire 来帮我们管理像上方这种简单的关系:
1 | <bean id="people" class="ruoxijun.pojo.People" autowire="byName"> |
这种方式会根据我们选的模式自动匹配对象对应的成员值,这里的 byName 模式表示 根据对象的成员变量名和bean文件中bean的id进行匹配 ,没找到赋值为null, byName 要保证变量名与bean的id一致。
此外还有一种模式 byType , 根据对象中成员变量的类型与bean文件中bean的类型进行匹配 :
1 | <bean id="people" class="ruoxijun.pojo.People" autowire="byType"> |
**byType **模式有必要保证匹配的类型在bean文件中全局 唯一 ,即需匹配类型在bean文件中有两个同类型的bean时将无法匹配并且 报错 ,没有时赋值为null。
Spring还提供了 constructor 自动赋值利用构造器赋值,它先按照 类型自动装配 存在多个时再按照 id属性名 装配,不存在赋值为null:
1 | <bean id="people" class="ruoxijun.pojo.People" autowire="constructor"> |