Spring的基本用法(大全-AOP)

Spring的AOP

面向切面编程(Aspect Orient Programming)分成两类:

  • 静态AOP实现:AOP框架在编译阶段对程序进行修改,即实现对目标类的增强,生成静态的AOP代理类。以Aspect为代表
  • 动态AOP实现:AOP框架在运行阶段动态生成AOP代理,即实现对目标对象的增强。以Spring AOP为代表 

AspectJ是基于Java语言的AOP框架。

  • 切面(Aspect):切面用于组织多个Advice,Advice放在切面中定义
  • 连接点(Joinpoint):程序执行过程中明确点,如方法的调用,或者异常的抛出。在Spring AOP中,连接点总是方法的调用
  • 增强处理(Advice):AOP框架在特定的切入点执行的增强处理。处理有“around”、“before”、“after”
  • 切入点(Pointcut):可以插入增强处理的连接点。当某个连接点满足指定要求时,该连接点将被添加增强处理,该连接点也就变成切入点。连接点+增强处理==切入点。包含切入点表达式和名字、任意参数的方法的签名。
    • AspectJ的切入点表达式:@Pointcut注解来标识
  • 引入:将方法或字段使用添加到被处理的类中。允许将新的接口引入到任何被处理的对象中去。
  • 目标对象:被AOP框架增强处理的对象。被增强的对象。AOP框架采用动态AOP实现,该对象是被代理对象。
  • 织入:将增强处理添加到目标对象中,并创建一个被增强的对象(AOP代理)的过程。

AOP代理就是AOP框架动态生成一个对象。该对象被作为目标对象。AOP代理包含目标对象的全部方法。AOP方法在特定切入点添加了增强处理,回调目标对象的方法。

Spring仅支持将方法调用作为连接点。如果需要对成员变量的访问和更新作为增强处理的连接点,考虑使用AspectJ。

  1. 定义普通业务组件
  2. 定义切入点,一个切入点可能横切多个业务组件
  3. 定义增强处理,增强处理就是在AOP框架为普通业务组件织入的处理动作。

AOP代理的方法 = 增强处理 + 目标对象的方法

零配置方式

@Aspect标识切面

@Pointcut标记切入点

不打算使用Spring的XMl Schema配置方式。

<!-- 启动@AspectJ支持 -->
<bean class="org.springframeworking.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" />
  1. 定义切面Bean。添加@Aspect注解为切面类,不会对该bean类进行增强
  2. 定义增强处理。类型如下:

Before增强处理

在切面类中用@Before("excution()")修饰一个方法,需要指定value属性值。该属性值为切入点表达式(如excution(org.aaa.bbb.*.*(..))。用于指定增强处理织入哪些切入点。

我的理解:用@Aspect修饰一个类为切面类,在用@Before("excution(org.aaa.bbb.*.*(..))")修饰类中的方法,在bbb包下所有的类的方法作为切入点(所有方法中的任意一个方法执行之前都要先调用一下用@before修饰的这个方法)

定义AfterReturning增强处理

目标方法完成后织入。

@AfterReturning注解的属性:

   pointcut/value:指定对应的切入点表达式

returning:指定一个形参名。访问目标方法的返回值,表示Advice可以定义与此相同的形参。限制目标方法返回指定类型的值或没有返回值。

AfterThrowing增强处理

处理程序未处理的异常,@AfterThrowing的属性如下

 pointcut/value:指定对应的切入点表达式

throwing:指定一个形参名。该形参可用于访问目标方法抛出的异常。限制目标方法必须抛出指定类型的异常。

After增强处理

无论目标方法成功完成还是遇到异常终止,他都会被织入。所以After必须准备处理正常返回和异常返回两种情况,常用于释放资源。

@after("excution()")

Around增强处理

before增强处理+AfterReturning增强处理。不同的是它可以决定目标方法在什么时候执行,是如何执行,甚至可以阻止目标方法的执行

既可以在目标方法执行之前织入,也可以在目标方法执行之后织入增强动作。

可以改变执行目标方法的参数值和返回值。

切入点表达式

切入点指示符有如下:

  • excution,属性有modifiers-pattern(指定方法的修饰符)、ret-type-pattern(指定方法的返回值)等
  • within:用于限定匹配特定类型的连接点。Spring AOP使用时,只能匹配方法执行的连接点。
  • this:用于限定AOP代理的必须是指定类型的实例,匹配该对象的所有连接点。Spring AOP使用时,只能匹配方法执行的连接点。
  • target:限定目标对象必须是指定类型的实例。Spring AOP使用时,只能匹配方法执行的连接点。
  • args:用于对连接点的参数进行限制,要求参数是指定类型的实例。Spring AOP使用时,只能匹配方法执行的连接点。

XML配置文件方式

自动扫描Bean组件和切面类<context:component-scan base-package=" "><context:include-filter type=" " expression="" /></context:component-scan>

<aop:aspectj-autoproxy/>显示启动自动代理。要么全部使用自动代理方式,要么使用<aop:config/>

注意:所有的切面、切入点和增强处理都要包含在<aop:config/>元素内部。<beans/>元素下可以包含多个<aop:config/>。

1.配置切面

<aop:aspect>的属性:

  • id:切面的标志名
  • ref:将ref所引用的普通Bean转换为切面Bean
  • order:定义该切面Bean的优先级。与@AspectJ的@Order注解作用一样

<aop:pointcut>的属性:

id:切入点的标志名

expression:切入点表达式

2.配置增强处理

<aop:before/>、<aop:after/>、<aop:afterreturning/>、<aop:afterthrowing/>、<aop:around/>

属性:

pointcut:切入表达式

pointcut-ref:指定一个已存在的切入点名称

method:指定方法名

throwing:指定形参名,<after-throwing/>有效

returning:指定形参名,<after-returning/>有效

Spring的事务

全局事务和局部事务

全局事务由应用服务器管理,需要JTA(Java Transaction API)支持

局部事务和底层采用持久化技术。采用JDBC持久化,需要使用Connection对象来操作事务;采用Hibernate持久化技术需要使用Session对象操作事务。

mybatis事务有两种使用方式:

(a):使用JDBC的事务管理机制:即使用java.Sql.Connection对象完成对事务的提交,回滚和关闭操作。

(b):使用MANAGED的事务管理机制:mybatis本身不会去实现事务管理的相关操作,而是交个外部容器(JBOSS,WebLogic)来管理事务。当与spring整合使用后,一般使用spring来管理事务。

声明式事务管理建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者织入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。

事务规则的属性值:事务隔离、事务传播、事务超时、只读状态。

事务传播行为

@Transactional所谓事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。在TransactionDefinition定义中包括了如下几个表示传播行为的常量:

  • TransactionDefinition.PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。
  • TransactionDefinition.PROPAGATION_REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起。
  • TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
  • TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
  • TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。
  • TransactionDefinition.PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
  • TransactionDefinition.PROPAGATION_NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。
属性 类型 描述
value String 可选的限定描述符,指定使用的事务管理器
propagation enum: Propagation 可选的事务传播行为设置
isolation enum: Isolation 可选的事务隔离级别设置
readOnly boolean 读写或只读事务,默认读写
timeout int (in seconds granularity) 事务超时时间设置
rollbackFor Class对象数组,必须继承自Throwable 导致事务回滚的异常类数组
rollbackForClassName 类名数组,必须继承自Throwable 导致事务回滚的异常类名字数组
noRollbackFor Class对象数组,必须继承自Throwable 不会导致事务回滚的异常类数组
noRollbackForClassName 类名数组,必须继承自Throwable 不会导致事务回滚的异常类名字数组

整合

启动Spring

web.xml文件中配置创建Spring容器,让Spring容器随着Web应用的启动而自动启动,借助ServletContextListener监听器完成。实现ContextLoaderListener接口

 <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

 载入Spring的配置文件

<!--spring配置文件的位置-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>

在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:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!-- 配置自动扫描的包 -->
    <context:component-scan base-package="com.qtu404">
        <!-- 扫描时跳过 @Controller 注解的JAVA类(控制器) -->
        <context:exclude-filter type="annotation"
                                expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <!-- 配置db.properyies文件位置 -->
    <bean id="configurer" class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer">
        <property name="locations" value="classpath:db.properties"></property>
    </bean>
    <!-- 配置数据源消息 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="${driver}"/>
        <property name="url" value="${url}"></property>
        <property name="username" value="${username}"></property>
        <property name="password" value="${password}"></property>
    </bean>
    <!-- 配置SqlSessionFactory -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="mapperLocations" value="classpath:com/qtu404/mapper/*.xml"></property>
    </bean>

    <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!-- 配置事务的传播性 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="get*" read-only="true"/>
            <tx:method name="add*" propagation="REQUIRED"/>
            <tx:method name="delete*" propagation="REQUIRED"/>
            <tx:method name="update*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

    <!-- 配置那些类的哪些方法需要参与事务 -->
    <aop:config>
        <aop:pointcut
                expression="execution(* com.qtu404.user.service.*.*(..))||execution(* com.qtu404.slide.service.*.*(..))"
                id="allMethod"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="allMethod"/>
    </aop:config>
</beans>

让Spring管理控制器

SpringMVC和Spring整合的配置文件springmvc-servlet.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:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p"
       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/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- scan the package and the sub package -->
    <context:component-scan base-package="com.qtu404"/>

    <!-- don't handle the static resource -->
    <mvc:default-servlet-handler/>

    <!-- if you use annotation you must configure following setting -->
    <mvc:annotation-driven/>
<!--文件上传-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
          p:defaultEncoding="UTF-8">
    </bean>

    <bean id="logger" class="com.qtu404.common.aop.Logger"/>
    <aop:config>

        <!--用户操作日志-->
        <aop:aspect id="userLog" ref="logger">
            <aop:pointcut id="userPointcut"
                          expression="execution(* com.qtu404.user.controller.UserController.*(..))"/>
            <aop:after method="saveLog" pointcut-ref="userPointcut"/>
        </aop:aspect>

        <!--幻灯片操作日志-->
        <aop:aspect id="slideLog" ref="logger">
            <aop:pointcut id="slidePointcut"
                          expression="execution(* com.qtu404.slide.controller.SlideController.*(..))"/>
            <aop:after method="saveLog" pointcut-ref="slidePointcut"/>
        </aop:aspect>

        <!--文件操作日志-->
        <aop:aspect id="fileLog" ref="logger">
            <aop:pointcut id="filePointcut"
                          expression="execution(* com.qtu404.slide.controller.FileController.*(..))"/>
            <aop:after method="saveLog" pointcut-ref="filePointcut"/>
        </aop:aspect>

        <!--文件夹作日志-->
        <aop:aspect id="folderLog" ref="logger">
            <aop:pointcut id="folderPointcut"
                          expression="execution(* com.qtu404.folder.controller.FolderController.*(..))"/>
            <aop:after method="saveLog" pointcut-ref="folderPointcut"/>
        </aop:aspect>
    </aop:config>

    <!-- configure the InternalResourceViewResolver -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          id="internalResourceViewResolver">
        <!-- 前缀 -->
        <property name="prefix" value="/"/>
        <!-- 后缀 -->
        <property name="suffix" value=".html"/>
    </bean>
</beans>

猜你喜欢

转载自blog.csdn.net/xuxuan1997/article/details/83997870
今日推荐