SpringIOC

xiaoxiao2021-02-28  145

Spring

一、简介

创建于2003年,是为了解决企业级开发的复杂性的,是一个封层的一站式轻量级的企业级开发框架。

二、使用Spring的优点

面试回答:

1. 低侵入式设计,代码污染极低 2. 独立于各种应用服务器,基于Spring框架的应用,可以真正实现Write Once,Run Anywhere的承诺 3. Spring的DI机制降低了业务对象替换的复杂性,提高了组件之间的解耦 4. Spring的AOP支持允许将一些通用任务如安全、事务、日志等进行集中式管理,从而提供了更好的复用 5. Spring的ORM和DAO提供了与第三方持久层框架的良好整合,并简化了底层的数据库访问 6. Spring并不强制应用完全依赖于Spring,开发者可自由选用Spring框架的部分或全部

三、Spring的七大功能模块

Spring框架是一个分层架构,有七个模块组成,分别是Spring Core ,AOP,DAO,MVC,WEB,ORM,Context。

核心容器(Spring Core)

Core模块是Spring框架最基础的模块,提供了IOC和DI。这里的基础概念是BeanFactory,它提供了对工厂模式的经典实现来消除对程序单例模式的需要,并正真允许你从程序逻辑中分离出依赖关系和配置。

Spring DAO模块

Spring 提供对JDBC的支持,对JDBC进行封装,允许JDBC使用Spring资源,并能统一管理JDBC事物,并不对JDBC进行实现。

Sprig MVC模块

WEB MVC模块为Spring提供了一套轻量级的MVC实现,在Spring的开发中,我们既可以用Struts也可以用Spring自己的MVC框架,相对于Struts,Spring自己的MVC框架更加简洁和方便。

Spring Web模块

WEB模块提供对常见框架如Struts1,WEBWORK(Struts 2),JSF的支持,Spring能够管理这些框架,将Spring的资源注入给框架,也能在这些框架的前后插入拦截器。

Spring AOP模块

AOP模块是Spring的AOP库,提供了AOP(拦截器)机制,并提供常用的拦截器,供用户自定义和配置。 AOP是OOP的延续,是(Aspect Oriented Programming)的缩写,意思是面向切面(方面)编程。 主要的功能是:日志记录,性能统计,安全控制,事务处理,异常处理等等

Spring Context模块

Context模块提供框架式的Bean访问方式,其他程序可以通过Context访问Spring的Bean资源,相当于资源注入。

Spring ORM模块

Spring 的ORM模块提供对常用的ORM框架的管理和辅助支持,Spring支持常用的Hibernate,ibtas,jdao等框架的支持,Spring本身并不对ORM进行实现,仅对常见的ORM框架进行封装,并对其进行管理。

四、Spring IOC容器与DI注入

IOC

IOC控制反转,控制关系发生转变,java面向对象编程的核心就是创建对象,构建对象间的关系,Spring IOC的本质就是创建对象的权利由原来的组件转移到了Spring容器,由容器控制对象的创建,建立对象间的关系。IOC的框架很多,目前主流是Spring IOC。

Spring IOC 容器

Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建 , 配置生命周期中的特定执行方法 !

一、Sping IOC 创建对象(创建对象)

Spring容器创建对象的步骤:

1. 搭建环境,导入jar包,主配置文件 2. 在配置文件中配置bean节点,将一个类的对象,加载到容器中,如下: <bean id="person" class="cn.xdl.bean.Person"></bean> 3. 在代码中获取容器对象 //我们在配置文件中加入的bean节点 对应的类, 已经被创建了对象 , 可以获取了 //默认情况下 这个对象, 跟随容器的创建而创建, 并且, 永远只有一个实例 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean.xml"); 4. 通过容器对象获取具体的bean,进行使用 1参getBean方法 * 参数1. 配置文件中的id值 context.getBean("person"); 2参getBean方法 * 参数1. 配置文件中的id值 * 参数2. 获取的对象类型 context.getBean("person", Person.class);

对象创建的方式(3种):

1. new 构造器创建,即通过传入类信息进行加载---常用 <bean id="" class=""> 2. 静态工厂创建 <bean id="key" class="工厂类的类信息" factory-method="getPerson"></bean> 3. 实例工厂创建 1. 先通过方式1 , 将实例工厂配置到容器中 <bean id="personFactory" class="实例工厂类的信息"></bean> 2. 再通过bean节点, 配置新的对象 指定具体对象的id 指定factory-bean属性(工厂对象的id属性) 指定factory-method属性(工厂对象中的工厂方法名) <bean id="key" factory-bean="personFactory" factory-method="getPerson"></bean> 注意: 三种不同的添加方式, 添加到容器中的对象, 默认情况下都是单例的 !

对象的作用域(scope)

1. singleton 单例 在每个Spring IoC容器中一个bean定义对应一个对象实例,默认项 使用单例的场景:工厂模式、连接池,组件中无成员变量或者成员变量均为常量时使用单例,如果有成员变量,当多个组件访问时会造成成员变量的值被覆盖的情况,非要使用单例,可以考虑加锁。 2. prototype 多例 一个bean定义对应多个对象实例 3. request 在一次HTTP请求中,一个bean定义对应一个实例,仅限于Web环境 4. session 在一个HTTP Session中,一个bean定义对应一个实例,仅限于Web环境 5. global Session 在一个全局的HTTP Session中,一个bean定义对应一个实例;仅在基于portlet的Web应用中才有意义,Portlet规范定义了全局Session的概念

对象的初始化和销毁

方式1. 指定当前容器所有的初始化方法与销毁方法: 初始化: default-init-method="方法名称" 容器默认在创建对象时, 会去检索此对象是否存在初始化方法 , 如果存在则调用, 不存在则不操作! 销毁时: default-destroy-method="方法名称" 容器默认在释放对象时, 会去检索此对象是否存在销毁方法 , 如果存在则调用, 不存在则不操作! 方式2. 指定某一个bean对象的初始化方法 与 销毁方法 初始化: init-method="方法名称" 当容器创建此对象时, 会去检索此对象是否存在初始化方法 , 如果存在则调用, 不存在则报错! 销毁时: destroy-method="方法名称" 当容器释放此对象时, 会去检索此对象是否存在销毁方法 , 如果存在则调用, 不存在则报错! 注意: 当方式一与方式二指定的方法不一致时 , 采用就近原则, 方法2生效 !

对象的创建时机与延迟(只针对单例模式) 复习单例模式: http://602173141.farbox.com/post/she-ji-mo-shi/dan-li-she-ji-mo-shi

容器实例化时除了实例化容器对象时,scope为单例的对象也同时创建。 所谓对象的延迟创建即将单例的对象由饿汉式变为懒汉式,具体的操作如下:

单例模式, 饿汉变懒汉

方式1 beans节点操作 default-lazy-init="true" : 容器中的所有单例对象, 饿汉变懒汉 容器中的所有单例对象, 延迟创建, 默认是容器创建时 立即创建对象 , 延迟后, 是第一次调用时创建! 方式2 bean节点操作 lazy-init="true" : 某一个bean对象, 饿汉变懒汉 某一个bean对象, 延迟创建, 默认是容器创建时 立即创建对象 , 延迟后, 是第一次调用时创建! 注意: 当方式一与方式二指定的方法不一致时 , 采用就近原则, 方法2生效 !

二、DI注入(建立对象之间的关系)

注入方式:set和构造器注入

set注入是在对象创建之后,通过set方法进行注入,而构造器注入是在创建对象时就已经进行了注入。

注入的参数: 基本数据类型、String、List、Set、Map、Property,对象,表达式注入#{id.属性}提取另一个对象中的属性值通过set或构造器注入给另外一个对象的属性。

set注入 格式:

基本数据类型和String类型进行注入: 格式:

property节点: 通过set方法, 设置一个属性的值 name属性: 表示的是 当前类中的属性的名称 value属性: 表示的是, 本次注入的值 案例: <bean id="id" class="类"> <property name="name" value="炙豪"></property> <property name="sex" value="女"></property> <property name="age" value="16"></property> --> </bean>

注入对象 格式:

property节点: 通过set方法, 设置一个属性的值 name属性: 表示的是 当前类中的属性的名称 ref: 表示的是, 本次要注入的对象在当前容器中的id值 案例: <bean id="id" class="类"> <property name="book" ref="book"></property> </bean>

注入集合 集合的定义: 集合的定义分为内部定义和外部定义,外部定义考虑的是重用性,内部注入如下:

注入List

案例:

<bean id="mingDa" class="cn.xdl.demo2.MingDa"> <property name="jiyous"> <!-- 通过在property中加入子节点list , 完成对于List集合类型的数据的注入 通过在property中加入子节点set , 完成对于set集合类型的数据的注入 list集合 和 set 集合的注入方式 ,除了节点名称不同, 其他地方完全一致 --> <list> <value>大卫</value> <value>俭娃</value> <value>杨策</value> <value>炙豪</value> <value>刘阳</value> <value>燕明</value> </list> </property> </bean>


2. 注入Set

案例: <bean id="mingDa" class="cn.xdl.demo2.MingDa"> <property name="name" value="明达"></property> <property name="age" value="79"></property> <property name="jiyous"> <!-- 通过在property中加入子节点list , 完成对于List集合类型的数据的注入 通过在property中加入子节点set , 完成对于set集合类型的数据的注入 list集合 和 set 集合的注入方式 ,除了节点名称不同, 其他地方完全一致 --> <set> <value>大卫</value> <value>俭娃</value> <value>杨策</value> <value>炙豪</value> <value>刘阳</value> <value>燕明</value> </set> </property> </bean>


3. 注入Map

案例: <bean id="mingDa2" class="cn.xdl.demo2.MingDa2"> <property name="name" value="明达"></property> <property name="age" value="79"></property> <property name="jiyous"> <map> <entry key="大卫" value="18"></entry> <entry key="杨策" value="8"></entry> <entry key="燕明" value="28"></entry> <entry key="炙豪" value="6"></entry> <entry key="俭娃" value="0"></entry> </map> </property> </bean>


4. 注入properties

案例: <bean id="mingDa3" class="cn.xdl.demo2.MingDa3"> <property name="name" value="明达"></property> <property name="age" value="79"></property> <property name="props"> <props> <prop key="大卫">18</prop> <prop key="燕明">2</prop> <prop key="炙豪">1</prop> <prop key="俭娃">1</prop> </props> </property> </bean>

集合的外部定义:

<util:list/set/map/properties> 可以声明一个外部定义的properties集合,读取一个property文件详情可参考 [http://blog.csdn.net/qq_26562641/article/details/53991411]

构造器注入

标记格式:<constructor-arg name = "" value = " [index = ""]> constructor节点: 通过构造器 , 注入属性的值 name属性: 这是一个容易混淆的地方 , 它指的其实是构造方法中形式参数列表中参数的名称,不是成员变量的名称。 value属性: 表示的是, 本次注入的值 index是参数的下标 案例: <bean id="id" class="类"> <constructor-arg name="nameX" value="大卫"></constructor-arg> <constructor-arg name="sexX" value="男"></constructor-arg> <constructor-arg name="ageX" value="26"></constructor-arg>

对象的自动装配(不常用)

我们可以在bean节点中, 添加autowire属性来完成自动装配的操作 属性取值范围: no : 默认设置 , 表示关闭自动装配 byName : 通过名称完成自动装配: 例如: 当前我们容器中存在一个对象, id为book; 而刚好当前的这个person类中有一个名称为book的属性 那么这个时候, 我们的容器, 会自动完成两个对象的关联 byName 不会判断传入的参数类型是否匹配, 只要名称相同, 就会强行建立依赖关系 , 导致报错! byType : 通过类型完成自动装配 例如: 当前我们容器中存在一个Book类的对象 而刚好我们当前的Person有一个Book类型的属性 我们的容器, 就会自动完成两个对象的关联 constructor 与byType的方式类似,不同之处在于它应用于构造器参数 autodetect 通过bean类来决定是使用constructor还是byType方式进行自动装配。如果发现默认的构造 器,那么将使用byType方式

通过注解方式进行DI注入

所谓通过注解的方式进行注入,其实质是通过在java代码上添加标记,所以需要有java源代码,是否使用注解注入,就要看是否有源代码。没有源代码的情况下只能使用xml进行配置。

使用注解配置的步骤: 1. 开启组件扫描,可以利用注解方式应用IOC。使用步骤如下: 2. 在applicationContext.xml中添加启用标记 <context:component-scan base-package=“包路径”/> 3. 在组件类中追加以下标记 @Component 通用注解 @Repository 持久化层组件注解 @Service 业务层组件注解 @Controller 控制层组件注解 4. 正常创建容器对象, getBean即可获得对象

注解方式的分类: 1. Scope

通过注解也可以指定scope @component(“person”) @Scope(“prototype”) 如果指定多例 , 那么生命周期不再由容器所控制 ,而是由程序员的代码来控制 ! 多例情况下, 销毁方法的指定是无效果的!

初始化与销毁方法

@PostConstruct 此注解添加到方法上, 可以将方法设置为初始化回调方法 @PreDestroy 此注解添加到方法上, 可以将方法设置为销毁回调方法

通过@Value 注入String以及基本数据类型值

案例:

通过表达式 @Value("#{book.name}") private String uname ; 普通方式 @Value("123456") private String upass ;

指定依赖关系

@Autowired/@Qualifier 可以处理构造器注入和Setter注入

@Resource 只能处理Setter注入,但大部分情况都是Setter注入

通过@Resource 建立依赖关系的流程 1. 先默认使用byName方式 , 去容器查找是否存在对应的对象 ,如果存在则赋值 2. 如果上面没有查询到, 再 根据byType, 进行容器的查询,如果存在则赋值 3. 如果上面两种方式 均未查到 ,则不赋值

三、Spring IOC 总结

Spring IOC,主要实现了两个核心的功能即对象的创建和对象关系的注入。其优点是有效的降低了各功能组件之间的耦合度。

所谓高内聚指的是一个软件模块是由相关性很强的代码组成,只负责一项任务,也就是常说的单一责任原则。 所谓低耦合是指一个完整的系统,模块与模块之间,尽可能的使其独立存在。即让每个模块,尽可能的独立完成某个特定的子功能。模块与模块之间的接口,尽量的少而简单。如果某两个模块间的关系比较复杂的话,最好首先考虑进一步的模块划分。这样有利于修改和组合。

所谓组件指的是接口的实现类,接口不是Spring容器的组件,因为接口不能创建对象,但在对象注入的过程中推荐使用接口注入,因为这样更灵活。

public class Demo{ public void Text1(){ //这里注入的是一个接口 private DeptDao deptDao; } } 将组件定义到Spring容器中时,可采用的方法有两类:xml注入和注解注入。

xml 定义:

<bean id = "" class = "">(常用)

通过注解

1. 开启注解扫描 2. 在要定义的组件上添加注解标签

4. 对象关系注入

转载请注明原文地址: https://www.6miu.com/read-69147.html

最新回复(0)