Spring学习8-Spring事务管理(AOP/声明式式事务管理)
一、基础知识普及
声明式事务的事务属性:
一:传播行为
二:隔离级别
三:只读提示
四:事务超时间隔
五:异常:指定除去RuntimeException其他回滚异常。
传播行为:
所谓事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。
spring的事务传播规则:
传播行为 |
意义 |
PROPAGATION_REQUIRED |
如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。 |
PROPAGATION_REQUIRES_NEW |
创建一个新的事务,如果当前存在事务,则把当前事务挂起。 |
PROPAGATION_SUPPORTS |
如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。 |
PROPAGATION_NOT_SUPPORTED |
以非事务方式运行,如果当前存在事务,则把当前事务挂起。 |
PROPAGATION_NEVER |
以非事务方式运行,如果当前存在事务,则抛出异常 |
PROPAGATION_MANDATORY |
如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。 |
PROPAGATION_NESTED |
如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行; |
这里需要指出的是,前面的六种事务传播行为是 Spring 从
EJB 中引入的,他们共享相同的概念。而 PROPAGATION_NESTED是 Spring 所特有的。以
PROPAGATION_NESTED
启动的事务内嵌于外部事务中(如果存在外部事务的话),此时,内嵌事务并不是一个独立的事务,它依赖于外部事务的存在,只有通过外部的事务提交,才能引起
内部事务的提交,嵌套的子事务不能单独提交。如果熟悉 JDBC
中的保存点(SavePoint)的概念,那嵌套事务就很容易理解了,其实嵌套的子事务就是保存点的一个应用,一个事务中可以包括多个保存点,每一个嵌套
子事务。另外,外部事务的回滚也会导致嵌套子事务的回滚。
隔离级别:
隔离级别是指若干个并发的事务之间的隔离程度:
spring的事务隔离级别:
隔离级别 |
含义 |
ISOLATION_DEFAULT |
这是默认值,表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常这值就是ISOLATION_READ_COMMITTED。 |
ISOLATION_READ_UNCOMMITTED |
该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读和不可重复读,因此很少使用该隔离级别。 |
ISOLATION_READ_COMMITTED |
该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。 |
ISOLATION_REPEATABLE_READ |
该隔离级别表示一个事务在整个过程中可以多次重复执 |
ISOLATION_SERIALIZABLE |
所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。 |
只读提示:
SessionFlush设置为none
(readOnly);
事务的只读属性是指,对事务性资源进行只读操作或者是读写操作。所谓事务性资源就是指那些被事务管理的资源,比如数据源、 JMS
资源,以及自定义的事务性资源等等。如果确定只对事务性资源进行只读操作,那么我们可以将事务标志为只读的,以提高事务处理的性能。在
TransactionDefinition 中以 boolean 类型来表示该事务是否只读。
事务超时间隔:
所谓事务超时,就是指一个事务所允许执行的最长时间,如果超过该时间限制但事务还没有完成,则自动回滚事务。在
TransactionDefinition 中以 int 的值来表示超时时间,其单位是秒。
声明式事务使用范例:
二、声明式事务配置的5中方式(方式四最常用)
方式一、基于Spring1.x,使用TransactionProxyFactoryBean为每个Bean生成一个代理。
<?xml version="1.0"
encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation"
value="classpath:hibernate.cfg.xml" />
<property name="configurationClass"
value="org.hibernate.cfg.AnnotationConfiguration"
/>
</bean>
<!-- 定义事务管理器(声明式的事务) -->
<bean
id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"
/>
</bean>
<!-- 配置DAO省略 -->
<!--
*******业务逻辑层(是对各个DAO层的正面封装)主要用到<<门面模式>>******
-->
<bean id="fundService"
class="com.jack.fund.service.serviceimpl.FundService">
<property name="producedao">
<ref bean="fundProduceDAO" />
</property>
</bean>
<bean
id="fundServiceProxy"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<!-- 配置事务管理器 -->
<property
name="transactionManager">
<ref bean="transactionManager"
/>
</property>
<!-- 此属性指定目标类本本身是否是代理的对象,如果目标类没有实现任何类,就设为true代表自己
可省略不写
-->
<property
name="proxyTargetClass">
<value>false</value>
</property>
<!-- 代理接口 可省略不写
-->
<property
name="proxyInterfaces">
<value>com.jack.fund.service.IFundService</value>
</property>
<!-- 目标bean -->
<property name="target">
<ref bean="fundService" />
</property>
<!-- 配置事务属性 -->
<property
name="transactionAttributes">
<props>
<prop
key="delete*">PROPAGATION_REQUIRED</prop>
<prop
key="add*">PROPAGATION_REQUIRED</prop>
<prop
key="update*">PROPAGATION_REQUIRED</prop>
<prop
key="save*">PROPAGATION_REQUIRED</prop>
<prop
key="find*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
</beans>
可以看出它适用于你的库表比较少的情况下,针对每一个功能模块配置一个业务代理服务。如果模块多大话,就显得代码有点多了,发现他们只是稍微一点不一样。这时我们就应该想到继承的思想。用第二种方法。
方式二、基于Spring1.x,使用TransactionProxyFactoryBean为所有Bean共享一个代理基类。
<?xml version="1.0"
encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation"
value="classpath:hibernate.cfg.xml" />
<property name="configurationClass"
value="org.hibernate.cfg.AnnotationConfiguration"
/>
</bean>
<!-- 定义事务管理器(声明式的事务) -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"
/>
</bean>
<!--
利用继承的思想简化配置,要把abstract="true"
-->
<bean
id="transactionBase"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
lazy-init="true" abstract="true">
<!-- 配置事务管理器 -->
<property
name="transactionManager">
<ref bean="transactionManager"
/>
</property>
<!-- 配置事务属性 -->
<property
name="transactionAttributes">
<props>
<prop
key="delete*">PROPAGATION_REQUIRED</prop>
<prop
key="add*">PROPAGATION_REQUIRED</prop>
<prop
key="update*">PROPAGATION_REQUIRED</prop>
<prop
key="save*">PROPAGATION_REQUIRED</prop>
<prop
key="find*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
<!--
而具体的模块可以简单的这样配置。只要指明它的parent(父类)就可以了。父类一般把abstract="true",因为在容器加载的时候不需要初始化,等到用的时候再有它的子类调用的时候,再去初始化。
-->
<!-- 配置DAO省略
-->
<!--
*******业务逻辑层(是对各个DAO层的正面封装)主要用到<<门面模式>>******
-->
<bean id="fundService"
class="com.jack.fund.service.serviceimpl.FundService">
<property name="producedao">
<ref bean="fundProduceDAO" />
</property>
</bean>
<bean id="fundServiceProxy"
parent="transactionBase" >
<property name="target">
<ref bean="fundService" />
</property>
</bean>
</beans>
这样配置的话,如果有多个像fundService这样模块时,可以少些很多重复的代码。
方式三、基于SpringAOP的拦截器(主要利用BeanNameAutoProxyCreator自动创建事务代理)
<?xml version="1.0"
encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation"
value="classpath:hibernate.cfg.xml" />
<property name="configurationClass"
value="org.hibernate.cfg.AnnotationConfiguration"
/>
</bean>
<!-- 定义事务管理器(声明式的事务) -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"
/>
</bean>
<bean id="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager"
ref="transactionManager" />
<!-- 配置事务属性 -->
<property
name="transactionAttributes">
<props>
<prop
key="delete*">PROPAGATION_REQUIRED</prop>
<prop
key="add*">PROPAGATION_REQUIRED</prop>
<prop
key="update*">PROPAGATION_REQUIRED</prop>
<prop
key="save*">PROPAGATION_REQUIRED</prop>
<prop
key="find*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
<bean
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<list>
<!-- 匹配所有的Service或者某个具体Service
-->
<value>*Service</value>
</list>
</property>
<property
name="interceptorNames">
<list>
<value>transactionInterceptor</value>
</list>
</property>
</bean>
<!-- 配置DAO省略 -->
<!--
*******业务逻辑层(是对各个DAO层的正面封装)主要用到<<门面模式>>******
-->
<bean id="fundService"
class="com.jack.fund.service.serviceimpl.FundService">
<property name="producedao">
<ref bean="fundProduceDAO" />
</property>
</bean>
</beans>
方式四、基于Spring2.x,使用tx标签配置的拦截器
<?xml version="1.0"
encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<bean
id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation"
value="classpath:hibernate.cfg.xml" />
<property name="configurationClass"
value="org.hibernate.cfg.AnnotationConfiguration"
/>
</bean>
<!-- 定义事务管理器(声明式的事务) -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"
/>
</bean>
<!--
定义JDBC的事务管理器
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"
/>
</bean>
-->
<!-- 定义切面
-->
<tx:advice id="txAdvice"
transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true" rollback-for="java.lang.Exception"/>
<!--其他方法设为如下传播属性
-->
<tx:method name="*" propagation="REQUIRED"
rollback-for="java.lang.Exception"/>
</tx:attributes>
</tx:advice>
<!--
定义切点和织入
-->
<aop:config>
<aop:pointcut id="interceptorPointCuts"
expression="execution(* com.spring.service.*.*(..))" />
<!--mgrService和empService省略
-->
<aop:pointcut id="leePointcut"
expression="bean(mgrService) || bean(empService)"
/>
<aop:advisor advice-ref="txAdvice"
pointcut-ref="interceptorPointCuts"
/>
<aop:advisor advice-ref="txAdvice"
pointcut-ref="leePointcut"
/>
<!-- 将authority转换成切面Bean
切面Bean的新名称为:authorityAspect
-->
<aop:aspect
id="authorityAspect" ref="authority">
<!--
定义一个Around增强处理,直接指定切入点表达式
以切面Bean中的authority()方法作为增强处理方法
-->
<aop:around pointcut="execution(*
org.crazyjava.message.service.impl.*Impl.*Message*(..))"
method="authority"/>
</aop:aspect>
</aop:config>
<!-- 定义一个普通Bean实例,该Bean实例将进行权限控制
-->
<bean id="authority"
class="org.crazyjava.message.authority.AuthorityInterceptor"/>
</beans>
关于权限拦截的类AuthorityInterceptor定义如下:
public class AuthorityInterceptor
{
//进行权限检查的方法
public
Object authority(ProceedingJoinPoint jp)
throws
java.lang.Throwable
{
HttpSession
sess = null;
//获取被拦截方法的全部参数
Object[]
args = jp.getArgs();
//遍历被拦截方法的全部参数
for (int i =
0 ; i < args.length ; i++ )
{
//找到HttpSession类型的参数
if (args[i]
instanceof HttpSession) sess =
(HttpSession)args[i];
}
//取出HttpSession里的user属性
Integer
userId = (Integer)sess.getAttribute("user");
//如果HttpSession里的user属性不为null,且大于0
if ( userId
!= null && userId >
0)
{
//继续处理
return
jp.proceed(args);
}
else
{
//如果还未登录,抛出异常
throw new
MessageException("您还没有登陆,请先登陆系统再执行该操作");
}
}
}
方式五、注解式声明事务(详见下篇博文)
其实他们还可以混合使用,方式三和方式四的混合使用:
<?xml version="1.0"
encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<!-- 其他省略
********************
AOP通知
********************
-->
<bean id="exception"
class="com.etc.advisor.ExceptionAdvisor"></bean>
<bean id="tx"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<constructor-arg index="0">
<ref bean="tm"/>
</constructor-arg>
<constructor-arg index="1">
<props>
<prop
key="*">PROPAGATION_REQUIRED</prop>
</props>
</constructor-arg>
</bean>
<aop:config
proxy-target-class="true">
<aop:pointcut id="p1" expression="(execution(*
com.etc.action.*.execute()))" />
<aop:pointcut id="p2" expression="(execution(*
com.etc.*.*.*(..)))" />
<aop:pointcut id="p3" expression="(execution(*
com.etc.service.*.*(..)))" /><!--
service的所有方法 -->
<aop:advisor advice-ref="tx"
pointcut-ref="p1"/>
<aop:advisor advice-ref="exception"
pointcut-ref="p2"/>
</aop:config>
</beans>
三、Spring事务配置示例
步骤一、配置文件(applicationContext.xml):
<?xml version="1.0"
encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="userservice"
class="com.sunflower.yuan.serviceimp.UserServiceImp">
<property name="jdbcTemplate">
<ref bean="jdbcTemplate"/>
</property>
</bean>
<bean id="datasource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"
value="com.mysql.jdbc.Driver"></property>
<property name="url"
value="jdbc:mysql://localhost:3306/mytest"></property>
<property name="username"
value="root"></property>
<property name="password"
value="root"></property>
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource">
<ref bean="datasource"/>
</property>
</bean>
<bean id="jdbcTemplate"
class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource">
<ref bean="mydatasource"/>
</property>
</bean>
<bean
id="transactionAttributeSource"
class="org.springframework.transaction.interceptor.
NameMatchTransactionAttributeSource">
<property name="properties">
<props>
<prop key="getMoney">
PROPAGATION_REQUIRED,ISOLATION_DEFAULT,-NoMoneyException
</prop>
</props>
</property>
</bean>
<!-- 声明式事务管理的代理类
-->
<bean
id="userTransaction"
class="org.springframework.transaction.interceptor.
TransactionProxyFactoryBean">
<property
name="proxyInterfaces">
<list>
<value>com.sunflower.yuan.servicedao.UserService</value>
</list>
</property>
<property name="target">
<ref bean="userservice"/>
</property>
<property
name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property
name="transactionAttributeSource">
<ref
bean="transactionAttributeSource"/>
</property>
</bean>
</beans>
声明式事务管理也是用动态代理模式来实现的,思想和AOP是一样的。主要是配置org.springframework.transaction.interceptor.TransactionProxyFactoryBean类。这个配置和AOP的配置非常相似。可以将事务属性单独写在org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource中,然后再用<property
name="transactionAttributeSource">引入,也可以直接用<property
name="transactionAttributes">配置事务属性。
<prop
key="getMoney">标签中的key="getMoney"表示对getMoney方法进行事务管理,也可使用通配符get*,表示对所有get前缀的方法进行事务管理。
事务属性的配置用","隔开,如下所示:
PROPAGATION, ISOLATION, readonly, -Exception, +Exception
PROPAGATION: 传播行为
ISOLATION: 隔离级别
readonly: 是否为只读事务(可选)
(+/-)Exception: 回滚规则。
如果是"-",遇到指定的Exception,事务回滚,如果是"+",事务不回滚。
UserService.java:
public interface UserService {
public void getMoney(int money, int id) throws
NoMoneyException;
}
UserServiceImp.java:
package com.sunflower.yuan.serviceimp;
import java.sql.ResultSet;
import java.sql.SQLException;
import
org.springframework.jdbc.core.JdbcTemplate;
import
org.springframework.jdbc.core.RowCallbackHandler;
import
com.sunflower.yuan.Exception.NoMoneyException;
import
com.sunflower.yuan.servicedao.UserService;
public class UserServiceImp implements
UserService {
private JdbcTemplate jdbcTemplate;
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Override
public void getMoney(int getMoney, int id) throws NoMoneyException
{
String sql = "select money from user where id=?";
Object[] params = new Object[] { new Integer(id) };
MyRowCallbackHandler rowCallBack = new
MyRowCallbackHandler();
jdbcTemplate.query(sql, params, rowCallBack);
if (rowCallBack.getMoney() > getMoney) {
sql = "update user set money=? where id=?";
Object[] params2 = new Object[] {
rowCallBack.getMoney() - getMoney, new Integer(id) };
jdbcTemplate.update(sql, params2);
throw new NoMoneyException("余额不足");
}
}
class MyRowCallbackHandler implements RowCallbackHandler {
private int money = 0;
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
@Override
public void processRow(ResultSet rs) throws SQLException {
this.money = rs.getInt("money");
}
}
}
这里要注意一点,要进行事务管理的方法,必须在方法外进行异常的抛出,这样事务管理器才能接收到,然后进行事务的回滚。如果用try-catch处理异常,将不会进行事务回滚。
借鉴博客地址:http://www.cnblogs.com/hanyuan/archive/2012/10/23/2732249.html
Spring学习8-Spring事务管理(AOP/声明式式事务管理)的更多相关文章
- spring 学习(三):aop 学习
spring 学习(三):aop 学习 aop 概念 1 aop:面向切面(方面)编程,扩展功能不修改源代码实现 2 AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码 3 aop底层使用动态代 ...
- Spring学习(六)-----Spring使用@Autowired注解自动装配
Spring使用@Autowired注解自动装配 在上一篇 Spring学习(三)-----Spring自动装配Beans示例中,它会匹配当前Spring容器任何bean的属性自动装配.在大多数情况下 ...
- Spring学习(十一)-----Spring使用@Required注解依赖检查
Spring学习(九)-----Spring依赖检查 bean 配置文件用于确定的特定类型(基本,集合或对象)的所有属性被设置.在大多数情况下,你只需要确保特定属性已经设置但不是所有属性.. 对于这种 ...
- Spring学习之Spring中AOP方式切入声明式事务
mybatis-spring官方文档说明 一个使用 MyBatis-Spring 的其中一个主要原因是它允许 MyBatis 参与到 Spring 的事务管理中.而不是给 MyBatis 创建一个新的 ...
- spring学习(三) ———— spring事务操作
前面一篇博文讲解了什么是AOP.学会了写AOP的实现,但是并没有实际运用起来,这一篇博文就算是对AOP技术应用的进阶把,重点是事务的处理. --wh 一.jdbcTemplate 什么是JdbcTem ...
- Spring学习13-中IOC(工厂模式)和AOP(代理模式)的详细解释
我们是在使用Spring框架的过程中,其实就是为了使用IOC,依赖注入,和AOP,面向切面编程,这两个是Spring的灵魂. 主要用到的设计模式有工厂模式和代理模式. IOC是工厂模式参考:设计模式- ...
- Spring学习总结(2)- AOP
一,什么是AOP AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件开发中 ...
- Spring学习笔记(13)——aop原理及拦截器
原理 AOP(Aspect Oriented Programming),也就是面向方面编程的技术.AOP基于IoC基础,是对OOP的有益补充. AOP将应用系统分为两部分,核心业务逻辑(Core bu ...
- Spring学习4-面向切面(AOP)之Spring接口方式
一.初识AOP 关于AOP的学习可以参看帮助文档:spring-3.2.0.M2\docs\reference\html目录下index.html的相关章节 1.AOP:Aspect ...
随机推荐
- 认识实验室信息管理系统(LIMS)
在当今互联网如日中天的大环境下,各种伴随着互联网的产物如p2p,o2o在如火如荼的进行着,吸引了大量的开发人员都涌向了这个行业,所有的技术似乎都在围绕着互联网发展,传统行业软件开发的人气和关注度就相形 ...
- 【转】【WPF】MVVM模式的3种command
1.DelegateCommand 2.RelayCommand 3.AttachbehaviorCommand 因为MVVM模式适合于WPF和SL,所以这3种模式中也有一些小差异,比如RelayCo ...
- Go 命令之 godep
本文参考:http://www.cnblogs.com/me115/p/5528463.html#h20 http://studygolang.com/articles/4385 关于Godep 发现 ...
- 如何使用Native Messaging API 打开window程序
问 如何使用Native Messaging API 打开window程序 cmd javascript terminal chrome Tychio 2013年03月26日提问 关注 1 关注 收藏 ...
- JavaScript标记上的defer与async的作用与区别
当浏览器遇到 script 标签时,文档的解析将停止,并立即下载并执行脚本,脚本执行完毕后将继续解析文档.但是我们可以将脚本标记为 defer,这样就不会停止文档解析,等到文档解析完成才执行脚本,也可 ...
- SpringMVC 中HttpMessageConverter简介和Http请求415 Unsupported Media Type的问题
一.概述: 本文介绍且记录如何解决在SpringMVC 中遇到415 Unsupported Media Type 的问题,并且顺便介绍Spring MVC的HTTP请求信息转换器HttpMessag ...
- State Pattern -- 状态模式原理及实现(C++)
主要参考<大话设计模式>和<设计模式:可复用面向对象软件的基础>两本书.本文介绍命令模式的实现. 问题出发点 在实际开发中,我们经常会遇到这种情况:一个对象有多种状态,在每一个 ...
- Java并发编程-CAS
CAS(Compare and swap)比较和替换是设计并发算法时用到的一种技术.简单来说,比较和替换是使用一个期望值和一个变量的当前值进行比较,如果当前变量的值与我们期望的值相等,就使用一个新值替 ...
- Android图片浏览器之图片删除
前一篇介绍了怎么从手机中读取图片文件,放入组件GridView实现网格效果的缩略图显示. 今天研究了对GridView中的子项(各张小图片)进行删除的操作,参考已有软件,长按图片跳出删除确认框. Gr ...
- Bootstrap系列 -- 21. 表单提示信息
平常在制作表单验证时,要提供不同的提示信息.在Bootstrap框架中也提供了这样的效果.使用了一个"help-block"样式,将提示信息以块状显示,并且显示在控件底部. < ...