Java康复性训练——Spring(2)

2016/7/22 posted in  Java  

AOP

AOP(Aspect Oriented Programming,面向切面编程),通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是软件开发的一个热点,也是Spring框架中的一个重要内容。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高开发效率。
主要功能是:日志记录、性能统计、安全控制、事务处理、异常处理等

Spring AOP实例

AOP的使用可以让我们在某个业务逻辑或事务执行的各个不同时期加入灵活的代码,让我们的权限控制、日志记录、性能统计等基础功能与业务逻辑彻底分离,降低耦合。这种执行方式称之为通知,通知有以下几种类型:

  1. 前置通知:在业务逻辑开始之前执行。
  2. 后置通知:在业务逻辑结束之后执行。
  3. 环绕通知:可以灵活配置业务逻辑的执行时间或是否执行业务逻辑,功能上有点类似于Filter。
  4. 返回通知:当业务逻辑执行完并返回非空数据时执行。
  5. 异常通知:当业务逻辑执行过程中产生异常时执行。

实例demo:

  1. 通知具体内容类:

    package site.zhanjingbo.advice;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    
    public class UserServiceAspect {
        public void doBefore(JoinPoint jp){
            System.out.println("请求类型:"+jp.getTarget().getClass().getName()+",请求方法:"+jp.getSignature().getName());
            System.out.println("开始添加用户:"+jp.getArgs()[0]);
        }
        public void doAfter(JoinPoint jp){
            System.out.println("请求类型:"+jp.getTarget().getClass().getName()+",请求方法:"+jp.getSignature().getName());
            System.out.println("完成添加用户:"+jp.getArgs()[0]);
        }
        public Object doAround(ProceedingJoinPoint pjp) throws Throwable{
            System.out.println("环绕前");
            Object retVal = pjp.proceed();
            System.out.println("环绕后");
            return retVal;
        }   
        public void doAfterThrowing(JoinPoint jp,Throwable ex){
            System.out.println("异常通知信息:"+ex.getMessage());
        }
        public void doAfterReturning(JoinPoint jp){
            System.out.println("返回通知");
        }
    }
    
  2. beans.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:aop="http://www.springframework.org/schema/aop"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop.xsd">
    
            <bean id="userService" class="site.zhanjingbo.service.impl.UserServiceImpl"/>
            <bean id="userServiceAspect" class="site.zhanjingbo.advice.UserServiceAspect" />
    
            <aop:config>
                <aop:aspect id="userServiceAspect" ref="userServiceAspect">
                    <!-- 声明一个切点 -->
                    <aop:pointcut expression="execution(* site.zhanjingbo.service.*.*(..))" id="businessService"/>  
                    <!-- 为切点添加通知 -->
                    <aop:before method="doBefore" pointcut-ref="businessService"/>
                    <aop:after method="doAfter" pointcut-ref="businessService"/>
                    <aop:around method="doAround" pointcut-ref="businessService" />
                    <aop:around method="doAround" pointcut-ref="businessService"/>
                    <aop:after-returning method="doAfterReturning" pointcut-ref="businessService"/>
                    <aop:after-throwing method="doAfterThrowing" pointcut-ref="businessService" throwing="ex"/>
                </aop:aspect>
            </aop:config>
    </beans>
    
  3. 执行顺序

Spring对Dao的支持

Spring发布以来很好的支持了Hibernate和Mybatis等ORM框架,只需要简单的配置,就可以很方便的实现dao的注入。

Spring对事务的支持

事务,是业务逻辑非常重要的一个概念。事务具有的原子性、一致性、隔离性、永久性是数据正确的保证。Spring为开发人员实现事务这个特性提供了非常方便的实现方式。

  1. 编程式事务管理:通过Spring提供的事务模板类org.springframework.transaction.support.TranscationTemplate来实现事务处理。
  2. 声明式事务管理:通过XML或注解配置的方式自动添加事务处理。
  3. 事务传播行为:Spring中,当一个service方法调用另外一个service方法的时候,因为每个service方法都有事务,这时候就出现了事务的嵌套,就产生了事务传播行为。

    1. PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
    2. PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。
    3. PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。
    4. PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。
    5. PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
    6. PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。
    <!-- (事务管理)transaction manager, use JtaTransactionManager for global tx -->
    <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="insert*" propagation="REQUIRED" />  
            <tx:method name="update*" propagation="REQUIRED" />  
            <tx:method name="edit*" propagation="REQUIRED" />  
            <tx:method name="save*" propagation="REQUIRED" />  
            <tx:method name="add*" propagation="REQUIRED" />  
            <tx:method name="new*" propagation="REQUIRED" />  
            <tx:method name="set*" propagation="REQUIRED" />  
            <tx:method name="remove*" propagation="REQUIRED" />  
            <tx:method name="delete*" propagation="REQUIRED" />  
            <tx:method name="change*" propagation="REQUIRED" />  
            <tx:method name="get*" propagation="REQUIRED" read-only="true" />  
            <tx:method name="find*" propagation="REQUIRED" read-only="true" />  
            <tx:method name="load*" propagation="REQUIRED" read-only="true" />  
            <tx:method name="*" propagation="REQUIRED" read-only="true" />  
        </tx:attributes>  
    </tx:advice>