Sping是分层的Java SE/EE 应用 Full-stack 轻量级开源框架,以Ioc(Inverse Of Control:反转控制)和AOP(Aspect Oriented Programming:面向切面编程)为内核,提供了展现层SpringMVC和持久层Spring JDBC以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的Java EE企业应用开源框架。
核心容器(Core Container),数据访问/集成(Data Access/Integration)层,Web层,AOP(Aspect Oriented Programming)模块,植入(Instrumentation)模块,消息传输(Messaging),测试(Test)模块。
耦合:程序间的依赖关系,包括类之间的依赖与方法间的依赖
解耦:
1.使用反射来创建对象,而避免使用new关键字
2.通过读取配置文件来获取要创建的对象全限定类名
普通程序中的耦合举例:(耦合现象严重)
持久层dao接口:提供保存账户方法
持久层dao实现类:实现保存账户的方法
业务层service接口:提供保存账户方法
业务层service实现类:创建持久层实现类的对象,由该对象实现保存账户的方法
模拟表现层client:在main函数中创建业务层实现类的对象,由该对象调用业务层实现类中的保存账户方法
思想概述:
把三层(dao,service,client)的对象都使用配置文件配置起来。
当启动服务器应用加载的时候,让一个工厂类中的方法通过读取配置文件,把这些对象创建出来并保存到一个map容器中。
在接下来的使用的时候,直接使用创建好的对象即可。
创建Bean对象的工厂:
baen在计算机英语中,是可重用组件的含义
javabean是用java语言编写的可重用组件。
全称为:inverse of control
是Spring框架的重要特征。把创建对象的权力交给框架。常见的方式有:依赖注入,依赖查找。
意义:削减耦合。
AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如安全性、异常处理和透明的持续性也都是如此,这种散布在各处的无关的代码被称为横切(cross cutting),在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
AOP技术恰恰相反,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。
使用"横切"技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。
init-method
实例创建时调用方法1.1:异常抛出增强
<aop:config>
<aop:aspect ref="增强方法所有的Bean">
<aop:after method="增强处理方法" pointcut-ref="切入点id" throwing="e"/>
</aop:aspect>
</aop:config>
1.2:环绕增强
<aop:config>
<aop:aspect ref="增强方法所有的Bean">
<aop:around method="增强处理方法" pointcut-ref="切入点id" />
</aop:aspect>
</aop:config>
1.3:构造注入
<bean id="唯一标识" class="类的全路径">
<constructor-arg name="参数名称" ref="依赖对象"/>
</bean>
注:有多个参数可以配置多个constructor-arg标签,除了name属性区别多个参数外,还可以使用constructor-arg标签中的index属性指定参数的索引,从0开始,constructor-arg提供了type属性,用以标识参数的类型
1.4:p空间注入
<bean id="唯一标识" class="全路径" p:"属性1"="注入的值1" p:"属性2"="注入的值2"/>
<bean id="唯一标识" class="全路径" p:dao-ref="注入的Bean"/>
(作用相同,推荐使用在不同分层上)
注:@Resource注解可以通过type参数指定要注入的Bean的具体类型
@AfterThrowing 抛出增强(目标方法发生异常,执行)
@Before 前置增强(目标方法执行之前,执行注解标注的内容)
@AfterReturning 后置增强(目标方法正常执行完毕后,执行)
@Around 环绕增强(目标方法执行前后,分别执行一些代码)
@After 最终增强 (无论如何都会执行,多用于释放资源)
@Aspect 定义切面 (作用是把当前类标识为一个切面供容器读取)
@Pointcut 定义一个表达式
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<aop:config>
<!--定义切面-->
<!--execution属性为该切入点的表达式,execution是切入点指示符,它的括号中是一个切入点表达式,切入点表达式支持模糊匹配,-->
<!--publie void *(entity.user):“*”表示匹配所有的方法名-->
<aop:pointcut id="SupplierMethod" expression="execution(* com.wei.Service.*.*(..))"/>
<!--把事务属性定义到切面里-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="SupplierMethod"/>
</aop:config>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.9</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
映射文件只需要配置类型别名和一些设置即可
<typeAliases>
<!--类型别名-->
<typeAlias type="com.wei.pojo.TSysUser" alias="tSysUser"/>
</typeAliases>
<!--引入properties文件-->
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="location" value="classpath:dataSoure.properties"/>
</bean>
<!--配置数据源-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${mysql.driver}"/>
<property name="url" value="${mysql.url}"/>
<property name="username" value="${mysql.username}"/>
<property name="password" value="${mysql.password}"/>
</bean>
要使用Spring-MyBatis一起使用,需要在 Spring 应用上下文中定义至少两样东西:一个 SqlSessionFactory
和至少一个数据映射器类。
在 MyBatis-Spring 中,可使用 SqlSessionFactoryBean
来创建 SqlSessionFactory
。 要配置这个工厂 bean,只需要把下面代码放在 Spring 的 XML 配置文件中
<!--配置SQLSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--引用数据源组件-->
<property name="dataSource" ref="dataSource"/>
<!--引用mybatis配置文件中的配置-->
<property name="configLocation" value="classpath:config.xml"/>
<!--配置SQL映射文件信息-->
<property name="mapperLocations">
<list>
<value>classpath:Mapper/*.xml</value>
</list>
</property>
</bean>
<!--获取SqlSession,SqlSessionTemplate就是Sqlsession-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
sqlsession.getmapper("这里给一个接口class)
注意:SqlSessionTemplate类实现了SqlSession接口,SqlSessionTemplate比SqlSession更加强大简介,能更好与SPring服务融合并简化部分流程化的工作,可以保证和当前Spring事务相关联,自动管理会话的生命周期,包括必要的事务关闭,提交和回滚操作。SqlSessionTemplate只能构造注入
假设你定义了一个如下的 mapper 接口:
那么可以通过 MapperFactoryBean
将接口加入到 Spring 中:
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="org.mybatis.spring.sample.mapper.UserMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
需要注意的特点是:
sqlSessionFactory()
方法注入sqlSessionFactory实例以创建SqlSessionTemplate实例配置好之后,你就可以像 Spring 中普通的 bean 注入方法那样,将映射器注入到你的业务或服务对象中。MapperFactoryBean
将会负责 SqlSession
的创建和关闭。 如果使用了 Spring 的事务功能,那么当事务完成时,session 将会被提交或回滚。最终任何异常都会被转换成 Spring 的 DataAccessException
异常。
<!--配置DAO-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<property name="basePackage" value="com.wei.Mapper"/>
</bean>
<!--配置扫描注解定义的业务bean-->
<context:comppnent-scan base-package="cn.cvs.service"/>
通过继承SqlSessionDaoSupport类获取getSqlSession()
实例处理数据,SqlSessionDaoSupport类中提供了setSqlSessionFactory()方法用来注入SqlSessionFactory并创建SqlSessionTemplate实例,同时,还提供了getSession()
方法并将创建好的SqlSessionTemplate实例返回,而Spring配置文件中也无需再配置SqlSessionTemplate,只需通过该DAO对象的setSqlSessionFactory()
方法为其注入SqlSessionFactory即可
<!--SupplierMapperimpl实现类继承了SqlSessionDaoSupport类-->
<bean id="supplierMapper" class="com.wei.Mapper.impl.SupplierMapperimpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
首先定义好接口和配置Mapper映射SQL,并实现接口,在spring容器导入tx命名空间和aop空间
配置DataSourceTransactionManager时,要为其注入事先定好的数据源组件
<!--配置声明事务-->
<!--定义事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--设置事务属性 transaction-manager属性需引用一个事务管理器Bean-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--<tx:attributes>里可以有多个tx:attributes,name属性是必须的,用于指定相匹配的方法,可使用通配符对方法进行设置-->
<tx:method name="*add"/>
<!--事务的属性说明:-->
<!--propagation;REQUIRED默认值表示如果存在一个事务,则支持当前事务:如果当前没有事务,则开启一个新事务-->
</tx:attributes>
</tx:advice>
属性 | 说明 |
---|---|
timeout | 设置一个事务所允许执行的最长时长(单位:秒),如果超过该时长且事务还没有完成,则自动回滚事务且出现org.springframework.transaction.TransactionTimedOutException异常 |
readOnly | 事务只读,指对事务性资源进行只读操作,不能修改。 |
rollbackFor | 指定对哪些异常回滚事务。默认情况下,如果没有抛出任何异常,或者抛出了检查时异常,依然提交事务。而rollbackFor可以控制事务在抛出某些检查时异常时回滚事务。 |
propagation | 指定事务传播行为,一个事务方法被另一个事务方法调用时,必须指定事务应该如何传播。 |
isolation | 指定事务隔离级别。 |
在业务类添加@Transactional注解即可为该类的所有业务统一添加事务处理。
属性 | 类型 | 说明 |
---|---|---|
propagation | 枚举型:Propagation | 可选的传播性设置。使用举例:@Transactional(propagation=Propagation.REQUIRES_NEW) |
isolation | 枚举型:Isolation | 可选的隔离性级别。使用举例:@Transactional(isolation=Isolation.READ_COMMITTED) |
timeout | int型(以秒为单位) | 事务超时。使用举例:@Transactional(timeout=10) |
readOnly | 布尔型 | 是否为只读型事务。使用举例:@Transactional(readOnly=true) |
rollbackFor | 一组Class类的实例,必须是Throwable的子类 | 一组异常类,遇到时必须进行回滚。使用举例:**@Transactional(rollbackFor={SQLException.class} ),多个异常可用英文逗号隔开** |
rollbackForClassName | 一组Class类的实例,必须是Throwable的子类** | 一组异常类名,遇到时必须进行回滚。使用举例:**@Transactional(rollbackForClassName={"SQLException"} ),多个异常可用英文逗号隔开** |
noRollbackFor | 一组**Class类的实例,必须是Throwable的子类** | 一组异常类,遇到时必须不回滚 |
noRollbackForClassName | 一组**Class类的实例,必须是Throwable的子类** | 一组异常类名,遇到时必须不回滚 |
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。