【异常抛出增强】

异常抛出异常最适合的应用场景:事务管理。

当参与事务的某个Dao发生异常时,事务管理器就必须回滚事务。

【异常抛出增强 例子】

【操作数据库的Dao类:PersonDao.java】

package com.Higgin.part2;

import java.sql.SQLException;
/**
* 模拟操作数据库并发生异常
*/

public class PersonDao {
//查询所有Person
public void getAllPerson(){
throw new RuntimeException("运行时异常...");
} //删除所有Person
public void deleteAllPerson() throws Exception{
throw new SQLException("删除数据异常...");
}
}

【抛出异常增强(事务管理器):TransactionManager.java】

package com.Higgin.part2;

import java.lang.reflect.Method;

import org.springframework.aop.ThrowsAdvice;

/**
* 抛出异常增强:事务管理器
* 实现的接口:ThrowsAdvice
* ThrowsAdvice异常抛出接口没有定义任何方法,是一个标识接口,在运行期间Spring使用反射机制自行判断
*/

public class TransactionManager implements ThrowsAdvice{ /**
* 我们必须使用 void afterThrowing(...)方法
* 方法名:必须为afterThrowing
* 方法入参:前三个入参Method method,Object[] args,Object target可选(要么三个都提供,要么都不提供),
* 最后一个入参是Throwable或其子类(这里用了子类Exception)
* 合法的例子:afterThrowing(SQLException ex)
* afterThrowing(RuntimeException ex)
* afterThrowing(Method method,Object[] args,Object target,RuntimeException ex)
*/

public void afterThrowing(Method method,Object[] args,Object target,Exception ex){
System.out.println("------抛出异常增强------");
System.out.println("method Name=="+method.getName());
System.out.println("获取抛出异常的信息:"+ex.getMessage());
System.out.println("成功滚回事务");
}
}

【Spring配置的文件:part2.xml】

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" 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" xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd"> <!-- 要增强的目标对象 -->
<bean id="target" class="com.Higgin.part2.PersonDao"/> <!-- 抛出异常的增强 -->
<bean id="transactionManager" class="com.Higgin.part2.TransactionManager"/> <!-- Spring代理工厂的成员变量配置(注意这里没有p:proxyInterfaces接口属性配置)-->
<bean id="personDao" class="org.springframework.aop.framework.ProxyFactoryBean"
p:interceptorNames="transactionManager"
p:target-ref="target"
p:proxyTargetClass="true"
/> </beans>

【测试类:TestTransactionManager.java】

package com.Higgin.part2.Test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.Higgin.part2.PersonDao; public class TestTransactionManager {
public static void main(String[] args) throws Exception {
ApplicationContext context=new ClassPathXmlApplicationContext("part2.xml");
PersonDao personDao=(PersonDao) context.getBean("personDao"); //分别执行下面两条
personDao.deleteAllPerson();
personDao.getAllPerson();
}
}

【运行personDao.deleteAllPerson() 结果】

【运行personDao.getAllPerson() 结果】

【分析】

关于标识接口(比如ThrowsAdvice抛出异常增强接口)

  标识接口是没有任何方法和属性的接口。标识接口不对实现者有任何语义上的要求,仅仅表明它的实现类是属于一个特定的类型。JAVA使用标识接口来标识某一类对象,第一,通过标识接口标识同一类型的类,这些类本身可能并没有具有相同的方法。第二,通过标识接口是程序或JVM采取一些特殊处理,如java.io.Serilizable,告诉JVM对象可以被序列化。

【引介增强】

  引介增强是一种特殊的增强,他不是在在目标方法周围织入增强,而是为目标方法创创建新的方法和属性,所以引介增强的连接点是类级别的,而非方法级别的。通过引介增强,我们可以为目标类添加一个接口的实现(即原来目标类未实现某个接口,通过引介增强可以为目标类创建实现某接口的代理)。

  Spring定义了引介增强接口IntroductionInterceptor,该接口没有定义任何方法,Spring为该接口提供DelegatingIntroductionInterceptor实现类,一般我们通过实现该类定义自己的引介增强类。

【引介增强 例子】

【模拟数据库操作 PersonDao.java】

package com.Higgin.part3;

/**
* 模拟数据库操作类
*/
public class PersonDao {
public void getAllPerson(){
System.out.println("查询数据库得到所有Person...");
}
}

【模拟性能监视类 PersonDaoMonitor.java】

package com.Higgin.part3;

/**
* 模拟性能检测类
*/
public class PersonDaoMonitor {
public static void begin(){
System.out.println("【操作数据库前】开始监测...");
} public static void end(){
System.out.println("【操作数据库后】结束检测,得到检测数据...");
}
}

【标识目标类是否支持性能监视的接口 Monitor.java】

package com.Higgin.part3;
/**
* 标识目标类是否支持性能监视的接口
*/
public interface Monitor {
/**
* 控制业务方法的性能监视功能 激活 or 关闭
*/
public void setMonitorActive(boolean active);
}

【为目标类引入性能可控功能 ControllerPersonDaoMonitor.java】

package com.Higgin.part3;

import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.support.DelegatingIntroductionInterceptor; /**
* ControllerPersonDaoMonitor类
* 为目标类引入性能可控功能
*
*/
public class ControllerPersonDaoMonitor extends DelegatingIntroductionInterceptor
implements Monitor{
/**
* ThreadLocal类型的成员变量 monitorStatusMap,用于保存性能监视开关状态
*/
private ThreadLocal<Boolean> monitorStatusMap =new ThreadLocal<>(); @Override
public void setMonitorActive(boolean active) {
monitorStatusMap.set(active);
} /**
* 拦截方法
*/
public Object invoke(MethodInvocation mi)throws Throwable{
Object obj=null;
//对于支持性能监视可控代理,通过判断其状态来决定是否开启性能监视
if(monitorStatusMap.get()!=null&&monitorStatusMap.get()){
PersonDaoMonitor.begin(); //调用PersonDaoMonitor的性能检测方法
obj=super.invoke(mi);
PersonDaoMonitor.end(); //调用PersonDaoMonitor的性能检测方法
}else{
obj=super.invoke(mi);
}
return obj;
} }

【Spring的xml配置方法 part3.xml】

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" 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" xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd"> <!-- 要增强的目标对象 -->
<bean id="target" class="com.Higgin.part3.PersonDao"/> <!-- 引介增强类 -->
<bean id="cpMonitor" class="com.Higgin.part3.ControllerPersonDaoMonitor"/> <!-- Spring代理工厂的成员变量配置 (引介增强实现了Monitor接口)-->
<bean id="personDao" class="org.springframework.aop.framework.ProxyFactoryBean"
p:proxyInterfaces="com.Higgin.part3.Monitor"
p:interceptorNames="cpMonitor"
p:target-ref="target"
p:proxyTargetClass="true"
/> </beans>

【测试类 TestControllerPersonDaoMonitor.java】

package com.Higgin.part3.Test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.Higgin.part3.Monitor;
import com.Higgin.part3.PersonDao; public class TestControllerPersonDaoMonitor {
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("part3.xml");
PersonDao personDao=(PersonDao) context.getBean("personDao");
//默认关闭性能检测
personDao.getAllPerson(); System.out.println("==============================="); //开启性能检测功能
Monitor mp=(Monitor) personDao;
mp.setMonitorActive(true); //再次调用业务方法
personDao.getAllPerson(); }
}

【运行结果】

【分析】

引介增强的配置与一般的配置有较大的区别:

1.需要指定引介增强需要实现的接口Monitor

2.由于只能通过为目标类创建子类的方式生成引介增强的代理,所以讲proxyTargetClass设置为true

21_AOP_Advice增强2(异常、引介)的更多相关文章

  1. SpringAOP03 项目脚手架、自定义注解、织入切面、引介增强

    1 项目脚手架 利用 Maven 进行创建 1.1 利用IDEA创建一个Maven原型项目 技巧01:原型Maven项目是没有webapp文件夹和resources项目文件夹的,需要自己手动创建:创建 ...

  2. AOP 增强方法

    Spring AOP 提供了 5 种类型的通知,它们分别是 Before Advice(前置通知).After Returning Advice(后置通知).Interception Around A ...

  3. 20_AOP_Advice增强1(前置、后置、环绕)

    [增强的类型] 1.前置增强:org.springframework.aop.BeforeAdvice. 由于Spring只支持方法级别的增强,所以MethodBeforeAdvice是目前可用的前置 ...

  4. Spring AOP增强(Advice)

    Sring AOP通过PointCut来指定在那些类的那些方法上织入横切逻辑,通过Advice来指定在切点上具体做什么事情.如方法前做什么,方法后做什么,抛出异常做什么. Spring中有两种方式定义 ...

  5. Spring支持5种类型的增强

    Spring支持5种类型的增强:1.前置增强:org.springframework.aop.BeforeAdvice代表前置增强,因为Spring只支持方法级的增强,所以MethodBeforeAd ...

  6. 基于XML配置的spring aop增强配置和使用

    在我的另一篇文章中(http://www.cnblogs.com/anivia/p/5687346.html),通过一个例子介绍了基于注解配置spring增强的方式,那么这篇文章,只是简单的说明,如何 ...

  7. Spring aop——前置增强和后置增强 使用注解Aspect和非侵入式配置

    AspectJ是一个面向切面的框架,它扩展了java语言,定义了AOP语法,能够在编译期提供代码的织入,所以它有一个专门的编译器用来生成遵守字节码字节编码规范的Class文件 确保使用jdk为5.0以 ...

  8. SSM-Spring-11:Spring中使用代理工厂Bean实现aop的四种增强

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 说说那四种增强:前置增强,后置增强,环绕增强,异常增强 那什么是代理工厂bean呢? org.springfr ...

  9. JDK1.7新特性(2):异常和可变长参数处理

    异常 jdk1.7对try--catch--finally的异常处理模式进行了增强,下面我们依次来看增强的方面. 1. 为了防止异常覆盖,给Throwable类增加了addSuppressed方法,可 ...

随机推荐

  1. c语言和c++的相互调用

    1.c与c++编译方式 (1)gcc和g++都可以编译.c文件,也都可以编译.cpp文件.g++和gcc是通过后缀名来辨别是c程序还是c++程序的(这一点与Linux辨别文件的方式不同,Linux是通 ...

  2. 【DP】【构造】NOIp模拟题 演讲 题解

        极其考思维的好题 题目背景 众所周知,$\mathrm{Zdrcl}$是一名天天$\mathrm{AK}$的高水平选手. 作为一民长者,为了向大家讲述自己$\mathrm{AK}$的经验,他决 ...

  3. Linux(1)-CentOS7下解决ifconfig command not found

    第一步: 输入ip addr 确认IP地址是否设置正常,设置好如下所示,如果没有获取到IP地址则设置一个即可. 第二步 确认sbin目录是否存在. cd /sbin 第三步 确认ifconfig命令是 ...

  4. AES/ECB/NoPadding 加减密

    package unit; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import org.apache. ...

  5. 前端 day 039

    一 .html css js 三大基本语言 定义文档的结构:HTML  修饰文档的样式 : css  行为 : JavaScript HTML 全称 Hyper Text Mackeup Langua ...

  6. Ionic3,安装,创建项目(一)

    Ionic3 简介:是一款html5的轻量级手机开发框架,基于angularjs.scss语法,ionic是一个轻量的手机UI库.并直接放弃了IOS 6和Android 4.1一下的版本支持. 安装: ...

  7. 【Tensorflow】 Object_detection之配置Training Pipeline

    参考:Configuring an object detection pipeline 1.config文件 配置好的config文件存放路径:object_detection/samples/con ...

  8. centos7 中文乱码问题解决方法

    1.查看是否安装中文包 可以使用下面的命名查看系统是否安装了中文安装包. locale -a |grep "zh_CN" 没有输出,说明没有安装,输入下面的命令安装: yum gr ...

  9. SVN创建资源库和远程连接配置

    SVN创建资源库和远程连接配置 本机安装的是TortoiseSVN-1.7.5.22551-win32-svn-1.7.3.msi 安装好后会在鼠标右键中出现如图最后两项的选项: 创建svn资源库: ...

  10. php获取今日、昨日、上周、本月的起始时间戳和结束时间戳的方法

    php 获取今日.昨日.上周.本月的起始时间戳和结束时间戳的方法,主要使用到了 php 的时间函数 mktime.下面首先还是直奔主题以示例说明如何使用 mktime 获取今日.昨日.上周.本月的起始 ...