Spring5总结

什么是Spring?       

        Spring 是分层的 Java SE/EE 应用 full-stack 轻量级开源框架,以 IoC(Inverse Of Control: 反转控制)和 AOP(Aspect Oriented Programming:面向切面编程)为内核,提供了展示层 Spring MVC 和持久层java

Spring JDBC 以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的 Java EE 企业应用开源框架。web

       

为何要使用Spring?

        在软件设计中,若是项目的耦合程度高,那么维护项目所须要的崇本也高。设计一个软件,其耦合度和内聚度一般做为衡量模块独立的标准。而划分模块的一个准则就是高内聚低耦合。spring

        耦合是不可能被彻底消除的,只能下降一部分的耦合能用数据耦合(模块间经过参数来传递数据,最低的耦合关系)就不用控制耦合(传递控制信号来执行操做),能用公共耦合(多个模块共拥有给全局数据项)就不用内容耦合(一个模块直接操做另外一个模块的数据,或不经过正常入口而转入另外一个模块,最高程度的耦合)。sql

        如何解决耦合?

        jdbc中经过反射来注册驱动image数据库

        因此使用配置文件配置key value的全限定类名字符串,就能够动态配置不一样的驱动。编程

        而且jdbc的这种方式再也不依赖具体的驱动类。session

        因此咱们可使用工厂模式,经过配置文件来配置建立对象的条件,来使用一个读取配置文件,并能建立和获取三层对象的工厂来解耦。框架

        比起直接建立对象的主动方式,用工厂来建立对象的方式是被动的。而这种被动接收的方式来获取对象,就是控制反转IOC的思想(下降程序的耦合),他是spring框架的核心之一。dom

 

 

如何使用Spring?

下面咱们用一个银行转帐的小demo用3种方式来进行配置(事务控制用了2种方式)
 

1、纯注解方式配置

项目结构:
image

 

 

 

 

config是配置目录:函数

    由SpringConfiguration做为总配置类

        JdbcConfig类和TransactionConfig类是配置数据库链接的类和事务控制的类

 

dao是持久层

 

 

domain存放的是实体类

 

service是服务层

 

 

resources

    jdbcConfig.properties中存放链接数据库的链接数据

 

test

    AccountServiceTest测试类

 

 

 

由运行顺序讲解代码

经过测试类

image

由于junit的原理,因此他是没法识别咱们是否使用了Spring框架的,因此必需要用spring的@Runwith来替换Junit原有的运行器

而后使用@ContextConfiguration的classes属性指定 spring 配置文件的位置

@ContextConfiguration 注解:

locations 属性:用于指定配置文件的位置。若是是类路径下,须要用 classpath:代表

classes 属性:用于指定注解的类。当不使用 xml 配置时,须要用此属性指定注解类的位置。

 

 

 

 

而后咱们经过注解进入配置文件类

image

 

扫描全部包就能够识别出全部的注解配置

导入了2个配置类

 

开启对AOP注解的支持

 

 

扫描包的话给出几个配置的典型例子

持久层的实现类:

image

@Repository持久层注解,

与@Component功能一致

做用:

把资源让 spring 来管理。至关于在 xml 中配置一个 bean。

属性:

value:指定 bean 的 id。若是不指定 value 属性,默认 bean 的 id 是当前类的类名。首字母小写。

@Controller @Service @Repository

他们三个注解都是针对第一个的衍生注解,他们的属性都是如出一辙的。

他们只不过是提供了更加明确的语义化。

@Controller:通常用于表现层的注解。

@Service:通常用于业务层的注解。

@Repository:通常用于持久层的注解。

细节:若是注解中有且只有一个属性要赋值时,且名称是 value,value 在赋值是能够不写。

 

@Autowired

做用:

自动按照类型注入。当使用注解注入属性时,set 方法能够省略。它只能注入其余 bean 类型。当有多个

类型匹配时,使用要注入的对象变量名称做为 bean 的 id,在 spring 容器查找,找到了也能够注入成功。找不到

就报错。

 

服务层的实现类:

image

@Service:业务层的注解

 

 

@Autowired自动注入

 

 

 

@Transactional

该注解的属性和 xml 中的属性含义一致。该注解能够出如今接口上,类上和方法上。

出现接口上,表示该接口的全部实现类都有事务支持。

出如今类上,表示类中全部方法有事务支持

出如今方法上,表示方法有事务支持。

以上三个位置的优先级:方法>类>接口

 

 

 

 

 

 

 

进入导入的第一个配置类

image

 

 

@Value注入基本类型和String类型的数据

 

 

 

 

 

 

 

 

 

 

 

@Bean标签,

做用:

该注解只能写在方法上,代表使用此方法建立一个对象,而且放入 spring 容器。

属性:

name:给当前@Bean 注解方法建立的对象指定一个名称(即 bean 的 id)。

 

 

 

 

 

 

而后看另外一个子配置类

image

 

 

 

 

 

仍然是提供了一个获取txManager对象的方法

 

 

 

 

而后是读取jdbc属性的配置,参数为类路径下的配置文件位置

image

 

 

 

 

最后@EnableTransactionManagement的配置是开启AOP的支持,配置了就开启,不配置就关闭

而后就实现了彻底基于注解的配置

<<<<<<<<<<<<<<<<<注解控制的细节<<<<<<<<<<<<<<<<<<

能够和上面进行对照更便于理解、使用

用于建立对象的


* 他们的做用就和在xml配置文件中编写一个<bean>标签实现的功能是同样的
* Component
*     做用:把当前对象存入spring容器中
*     属性:
*         value:用于指定bean的id,当咱们不写时,默认值是当前类名且首字母变为小写
*         Controller:通常用在表现层
*         Service:通常用在业务层
*         Repository:通常用在持久层
* 以上三个注解他们的做用和属性与Component是如出一辙的
* 他们三个是spring框架为咱们提供明确的三层使用的注解,使咱们的三层对象更加清晰
*

* 用于注入数据的


* 他们的做用就和在xml配置文件中的<bean>标签中写<property>标签的做用是同样的
* Autowired
* private IAccountDao accountDao1=null;
* 访问修饰符 数据类型    变量名称       数据类型
* 注入时主要考虑变量名称与id的匹配
*     做用:
*         自动按照类型注入(接口的名称,而非本身起的id)。只要容器中有惟一的一个bean对象类型和要注入的变量类型匹配就能够注入成功。
*         若是ioc容器中没有任何bean的类型和要注入的变量类型匹配就报错。
* 出现位置:
*     变量、方法
* 细节:
*     在使用注解注入时,set方法不是必须的。
* Qualifier:
*     做用:
*         在按照类中注入的基础上再按照名称注入。他在给类成员注入时不能单独使用(要与Autowired配合)。可是给方法参数注入时能够
* Resource:
*     做用:
*         直接按照bean的id注入。他能够独立使用
*     属性:
* name:用于指定bean的id。
* 以上3中注入都只能注入其余bean类型的数据,而基本类型和String类型没法使用上述注解实现
* 另外集合类型的注入只能经过xml来实现。
*
* value
*     做用:
*         用于注入基本类型和String类型的数据
*     属性:
*         value:用于指定数据的值。它可使用spring中SpEL(也就是spring的el表达式)
* SpEL的写法:${表达式},看el表达式出现的位置
*

* 用于改变做用范围的


* 他们的做用和在bean标签中使用scope属性实现的功能是同样的
* Scope
*     做用:
*         用于指定bean的做用范围
*     属性:
*         value:指定范围的取值。经常使用取值:singleton prototype,不写默认是单例的

* 和生命周期相关的


* 他们的做用和在bean标签中使用init-method和destroy-method的做用是同样的
* PostConstruct
*        做用:
*         用于指定初始化方法
* PreDestroy
*     做用:
*         用于指定销毁方法(多例对象的销毁,spring并不负责)

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

 

 

 

 

2、下面是以xml为主的配置方式

事务控制方面选Z额了spring编程式事务控制

image

 

 

 

 

dao是持久层

 

 

domain存放的是实体类

 

service是服务层

 

 

 

resources

    bean.xml中存放了基于xml的spring配置信息

 

 

test

    AccountServiceTest测试类

 

如下全部重复的部分不作解释:

image

 

@ContextConfiguration 注解:使用locations 属性来读取配置文件

locations 属性:用于指定配置文件的位置。若是是类路径下,须要用 classpath:代表

classes 属性:用于指定注解的类。当不使用 xml 配置时,须要用此属性指定注解类的位置。

 

 

而后咱们进入配置文件

image

 

关于bean标签和依赖注入的细节在下面:

 

 

 

 

 

依赖注入使用的是下面依赖注入方法中的set方法

 

 

 

 

 

 

 

 

image

 

 

用TransactionTemplate手动管理事务

 

 

<<<<<<<<<<<<<<<<xml配置中的细节<<<<<<<<<<<<<<<<

bean标签把对象的建立交给spring来管理

 

spring对bean的管理细节

     一、建立bean的三种方式

     二、bean对象的做用范围

     三、bean对象的生命周期

 

建立bean的三种方式

a.使用默认的构造函数建立

<!--此种方式是:

在spring配置文件中使用bean标签,配以id与class属性以后,且没有其余属性和标签时。

采用的就是默认构造函数建立bean对象,此时若是类中没有默认构造函数,对象则没法建立。

-->

<!--<bean id="accountService" class="com.lky.service.impl.AccountServiceImpl"></bean>-->

b.使用普通工厂中的方法建立对象(使用某个类中的方法建立对象,并存取容器)

<!-- 此种方式是:

先把工厂的建立交给 spring 来管理。

而后在使用工厂的 bean 来调用里面的方法

factory-bean 属性:用于指定实例工厂 bean 的 id。

factory-method 属性:用于指定实例工厂中建立对象的方法。

-->

<!--<bean id="instanceFactory" class="com.lky.factory.InstanceFactory"></bean>-->
<!--<bean id="accountService" factory-bean="instanceFactory" factory-method="getAccountService"></bean>-->

c.使用静态工厂中的静态方法建立对象(使用摸个类中的静态方法建立对象,并存入容器)

<!-- 此种方式是:

使用 StaticFactory 类中的静态方法 createAccountService 建立对象,并存入 spring 容器

id 属性:指定 bean 的 id,用于从容器中获取

class 属性:指定静态工厂的全限定类名

factory-method 属性:指定生产对象的静态方法

-->

<!--<bean id="accountService" class="com.lky.factory.StaticFactory" factory-method="getAccountService"></bean>—>

bean的做用范围调整(spring对象默认为单例的)

<!--

bean标签中的scope属性:

      做用:用于指定bean的做用范围

      取值:

          singleton:单例,默认值

          prototype:多例的

          request:做用于web应用的请求范围

          session:做用于web应用的会话范围

          global-session:做用于集群环境的会话范围(全局会话范围),当不是集群环境时,就是session

-->

<!--<bean id="accountService" class="com.lky.service.impl.AccountServiceImpl" scope="prototype"></bean>—>

 

bean对象的生命周期

<!--

单例对象

    出生:容器建立时

    活着:容器还在

    死亡:容器销毁

多例对象

    出生:使用对象时,spring为咱们建立

    活着:对象在使用就活着

    死亡:当对象长时间不用且没有别的对象引用时,由java的垃圾回收器回收

—>

 

sprig中的依赖注入

<!--
依赖注入:
Dependency Injection
IOC的做用:
下降程序间的耦合(依赖关系)
依赖关系的管理:
都交给spring来维护
当前类须要用到其余类的对象,由spring为咱们提供,咱们只须要在配置文件中说明
依赖关系的维护:
称之为依赖注入
依赖注入:
能注入的数据有3类:
基本类型和String
其余bean类型(在配置文件中或注解配置过的bean)
复杂类型/集合类型
注入的方式:
1。使用构造函数提供
2。使用set方法
3。使用注解提供
—>

<!--构造函数注入


使用的标签:constructor-arg
出现的位置:bean标签内部
标签中的属性
type:用于指定要注入的数据的类型,该数据类型也是构造函数中某个或某些参数的类型(没法区分多个,因此不能独立实现)
index:用于指定要注入的数据给构造函数中指定索引位置的参数赋值,从0开始(能够独立实现,但必须清楚类型)
name:用于指定给构造函数中指定名称的参数赋值(经常使用)
=============以上3个用于指定给构造函数中的参数赋值=================================
value:用于提供基本类型和String类型的数据
ref:用于指定其余的bean类型的数据。指的是spring的IOC核心容器中出现过的bean对象

优点:
在获取bean对象时,注入数据时必须的操做,不然对象没法建立成功。
缺点:
改变了bean对象的实例化方式,使建立对象时,若是不使用这些数据,也必须提供。
-->
<bean id="accountService" class="com.lky.service.impl.AccountServiceImpl">
<constructor-arg name="name" value="柯"></constructor-arg>
<constructor-arg name="age" value="18"></constructor-arg>
<constructor-arg name="birthday" ref="time"></constructor-arg>
</bean>

<!--配置一个时间对象-->
<bean id="time" class="java.util.Date"></bean>
 

<!--set方法注入 更经常使用


使用的标签:property
出现的位置:bean标签内部
标签中的属性:
name:用于指定给构造函数中指定名称的参数赋值(经常使用),从set方法中寻找
=============以上3个用于指定给构造函数中的参数赋值=================================
value:用于提供基本类型和String类型的数据
ref:用于指定其余的bean类型的数据。指的是spring的IOC核心容器中出现过的bean对象
优点:
建立对象时没有明确的限制,能够直接使用默认构造函数
缺点:
若是摸个成员必须有值,则获取对象时,set方法没法保证必定注入(可能不执行set),
-->
<bean id="accountService2" class="com.lky.service.impl.AccountServiceImpl2">
<property name="name" value="柯雨"></property>
<property name="age" value="21"></property>
<property name="birthday" ref="time"></property>
</bean>
 

<!--复杂类型的注入,集合类型


用于给list集合注入的标签有:
list array set
用于给Map集合注入的标签有:
map props
结构相同,标签能够互换
-->
<bean id="accountService3" class="com.lky.service.impl.AccountServiceImpl3">
<property name="myStrs">
<array>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</array>
</property>

<property name="myList">
<list>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</list>
</property>

<property name="mySet">
<set>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</set>
</property>

<property name="myMap">
<map>
<entry key="a" value="AAA"></entry>
<entry key="b">
<value>BBB</value>
</entry>
</map>
</property>

<property name="myProps">
<props>
<prop key="c">CCC</prop>
<prop key="d">DDD</prop>
</props>
</property>
</bean>

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

由于采用xml文件配置,因此类中都是基本代码。

重点帖一下服务层实现的部分,由于服务层进行着事务控制

image

 

 

 

 

 

 

 

 

 

 

spring编程式事务控制,经过使用transactionTemplate中的excute方法

excute在执行时会使用doInTransaction(status)的方法,而且在执行时,这个doInTransaction的部分实现了rollback,commit等事务操做。

 

 

 

 

 

 

 

 

 

由于经过代码来实现事务很是麻烦,增长开发难度,而且会增长业务层重复的代码。因此通常不多使用。

 

为何使用银行转帐为例子?

是由于银行转帐其实是进行事务控制,而事务控制是许多业务的必要部分。

持久层connection 对象的 setAutoCommit(true)方法会使单条sql语句的事务获得成功的执行,但若是业务层同时执行多个持久层方法,而且在中间产生了异常,业务层的此次调用在不进行处理的状况下是没法进行总体自动回滚的,他会执行能成功的语句,回滚失败的语句。此时咱们的银行转帐会出现严重的问题。咱们也能够是用try catch finally的方式去处理,可是由于许多业务都涉及了事务控制,这样去处理,重复的代码量极大,是会增长开发成本的。

若是解决代码重复的问题?

动态代理,咱们能够经过动态代理,使须要进行事务控制的方法通过代理类,从而实现事务控制。

而动态代理的实现方式有两种,基于接口和基于子类。

而在spring中,经过配置,框架会根据目标类是否实现了接口来决定采用哪一种动态代理的方式。

这这种解决上述问题的spring配置,称之为AOP

<<<<<<<<<<<这里是aop的相关术语解释<<<<<<<<<<<

Joinpoint(链接点):

    所谓链接点是指那些被拦截到的点。在 spring 中,这些点指的是方法,由于 spring 只支持方法类型的链接点。

Pointcut(切入点):

    所谓切入点是指咱们要对哪些 Joinpoint 进行拦截的定义。

Advice(通知/加强):

    所谓通知是指拦截到 Joinpoint 以后所要作的事情就是通知。

    通知的类型:前置通知,后置通知,异常通知,最终通知,环绕通知。

Introduction(引介):

    引介是一种特殊的通知在不修改类代码的前提下, Introduction 能够在运行期为类动态地添加一些方法或 Field。

Target(目标对象):

    代理的目标对象。

Weaving(织入):

    是指把加强应用到目标对象来建立新的代理对象的过程。

    spring 采用动态代理织入,而 AspectJ 采用编译期织入和类装载期织入。

Proxy(代理):

    一个类被 AOP 织入加强后,就产生一个结果代理类。

Aspect(切面):

    是切入点和通知(引介)的结合。

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

3、基于AOP方式的声明式事务管理的配置过程:

重复的部分再也不赘述

首先是执行的测试类

image

 

 

 

 

 

 

 

 

 

 

 

而后是读取的bean.xml配置文件

image

 

 

这里的spring关于aop的配置约束能够在spring官网的Core包中找到

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

image

 

 

 

 

 

 

 

首先配置事务管理器

 

而后配置事务的通知(加强)去引用事务管理器,而这个通知,

就是公共重复的代码部分,也是咱们以前想经过动态代理去加强的部分。

 

 

 

对转帐方法设定了必定有事务的事务传播行为

对全部的find开头方法进行了查询方式的事务加强

 

image

 

 

切入点表明咱们对业务层实现下的全部方法(链接点)进行拦截

 

而后把切入点与上述的通知创建关系。

 

 

即经过使用AOP的方式实现了事务的控制。

相关文章
相关标签/搜索