AOP 增强方法
Spring AOP 提供了 5 种类型的通知,它们分别是 Before Advice(前置通知)、After Returning Advice(后置通知)、Interception Around Advice(周围通知)、Throws Advice(异常通知)和 Introduction Advice(引介通知)。

下面分别进行介绍。
- 前置增强 (org.springframework.aop.BeforeAdvice) 表示在目标方法执行前来实施增强
- 后置增强 (org.springframework.aop.AfterReturningAdvice) 表示在目标方法执行后来实施增强
- 环绕增强 (org.aopalliance.intercept.MethodInterceptor) 表示在目标方法执行前后同时实施增强
- 异常抛出增强 (org.springframework.aop.ThrowsAdvice) 表示在目标方法抛出异常后来实施增强
- 引介增强 (org.springframework.aop.introductioninterceptor) 表示在目标类中添加一些新的方法和属性
前置增强:
import org.springframework.aop.BeforeAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.framework.ProxyFactory; import java.lang.reflect.Method; public class Main{
public static void main(String[] args) {
//1、不使用xml配置实例化
Worker target=new DigWorker();
BeforeAdvice advice=new WearingBeforeAdvice();
//Spring提供的代理工厂
ProxyFactory pFactory=new ProxyFactory();
// //指定做优化,又将使用cglib动态
// pFactory.setOptimize(true);
//
// //指定对接口进行代理,通过JDK动态代理
// pFactory.setInterfaces(target.getClass().getInterfaces()); //设置代理目标,默认使用Cglib动态代理
pFactory.setTarget(target); //为代理目标添加前置增强,这里会为目标的每个方法都增加增强
pFactory.addAdvice(advice);
//生成代理实例
Worker proxy=(Worker)pFactory.getProxy();
proxy.getTool("钻机");
proxy.digSomething("煤炭");
proxy.initWork();
}
} interface Worker {
void getTool(String tool);
void digSomething(String type);
void initWork();
} class DigWorker implements Worker{ @Override
public void getTool(String tool) {
System.out.println("---------------调用方法--------------");
System.out.println("领取工具:"+tool);
// throw new RuntimeException("运行异常");
} @Override
public void digSomething(String type) {
System.out.println("---------------调用方法--------------");
System.out.println("开始卖力挖取:"+type); } @Override
public void initWork() {
System.out.println("生成一个DigWorker实例");
}
} class WearingBeforeAdvice implements MethodBeforeAdvice {
public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
if(arg1.length>0) {
String thing = (String) arg1[0];
System.out.println("--------------进行前置增强---------------");
System.out.println("得到" + thing + "之前先穿上工作服!!");
}else{
System.out.println("--------------进行前置增强2---------------");
}
}
}
--------------进行前置增强---------------
得到钻机之前先穿上工作服!!
---------------调用方法--------------
领取工具:钻机
--------------进行前置增强---------------
得到煤炭之前先穿上工作服!!
---------------调用方法--------------
开始卖力挖取:煤炭
--------------进行前置增强2---------------
生成一个DigWorker实例
前置和后置:
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import java.lang.reflect.Method; public class Main{
public static void main(String[] args) {
//2、下面使用Spring的xml配置实例化
ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
//worker1带前置和后置增强
Worker worker1=(Worker)ctx.getBean("worker1");
System.out.println("worker1进入工作:");
worker1.getTool("锄头");
}
} interface Worker {
void getTool(String tool);
void digSomething(String type);
void initWork();
} class DigWorker implements Worker{ @Override
public void getTool(String tool) {
System.out.println("---------------调用方法--------------");
System.out.println("领取工具:"+tool);
// throw new RuntimeException("运行异常");
} @Override
public void digSomething(String type) {
System.out.println("---------------调用方法--------------");
System.out.println("开始卖力挖取:"+type); } @Override
public void initWork() {
System.out.println("生成一个DigWorker实例");
}
} class WearingBeforeAdvice implements MethodBeforeAdvice {
public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
if(arg1.length>0) {
String thing = (String) arg1[0];
System.out.println("--------------进行前置增强---------------");
System.out.println("得到" + thing + "之前先穿上工作服!!");
}else{
System.out.println("--------------进行前置增强2---------------");
}
}
} class WeaningAfterAdvice implements AfterReturningAdvice {
@Override
public void afterReturning(Object arg0, Method arg1, Object[] arg2,
Object arg3) throws Throwable {
System.out.println("--------------进行后置增强---------------");
System.out.println("工作结束,请先脱掉工作服");
}
}
benas文件:
<?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-3.2.xsd">
<!-- 要进行增强的目标 -->
<bean id="target" class="com.company.DigWorker" init-method="initWork"/> <!-- 前置增强的方法 -->
<bean id="beforeAdvice" class="com.company.WearingBeforeAdvice" />
<!-- 后置增强的方法 -->
<bean id="afterAdvice" class="com.company.WeaningAfterAdvice" /> <!--同时设置前置增强和后置增强方法 -->
<bean id="worker1" class="org.springframework.aop.framework.ProxyFactoryBean"
p:proxyInterfaces="com.company.Worker" p:interceptorNames="beforeAdvice,afterAdvice"
p:target-ref="target" lazy-init="true"/>
</beans>
Result:
生成一个DigWorker实例
worker1进入工作:
--------------进行前置增强---------------
得到锄头之前先穿上工作服!!
---------------调用方法--------------
领取工具:锄头
--------------进行后置增强---------------
工作结束,请先脱掉工作服
环绕增强:
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.aopalliance.intercept.MethodInterceptor; public class Main{
public static void main(String[] args) {
//2、下面使用Spring的xml配置实例化
ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
//work2带环绕增强
Worker worker2=(Worker)ctx.getBean("worker2");
System.out.println("worker2进入工作:");
worker2.getTool("钻机");
}
} interface Worker {
void getTool(String tool);
void digSomething(String type);
void initWork();
} class DigWorker implements Worker{ @Override
public void getTool(String tool) {
System.out.println("---------------调用方法--------------");
System.out.println("领取工具:"+tool);
// throw new RuntimeException("运行异常");
} @Override
public void digSomething(String type) {
System.out.println("---------------调用方法--------------");
System.out.println("开始卖力挖取:"+type); } @Override
public void initWork() {
System.out.println("生成一个DigWorker实例");
}
} class WearingInterceptor implements MethodInterceptor{
@Override
public Object invoke(MethodInvocation arg0) throws Throwable {
Object[] args=arg0.getArguments();//目标方法入参
String toolname=(String)args[0];
System.out.println("--------------环绕增强开始---------------");
System.out.println("得到"+toolname+"之前先穿上工作服");
Object object=arg0.proceed();
System.out.println("工作结束,请先脱掉工作服");
System.out.println("--------------环绕增强结束---------------");
return object;
}
}
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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<!-- 要进行增强的目标 -->
<bean id="target" class="com.company.DigWorker" init-method="initWork"/>
<!-- 环绕增强的方法 -->
<bean id="aroundAdvice" class="com.company.WearingInterceptor" />
<!--设置环绕增强方法 -->
<bean id="worker2" class="org.springframework.aop.framework.ProxyFactoryBean"
p:proxyInterfaces="com.company.Worker" p:interceptorNames="aroundAdvice"
p:target-ref="target" lazy-init="true"/>
</beans>
Result:
生成一个DigWorker实例
worker2进入工作:
--------------环绕增强开始---------------
得到钻机之前先穿上工作服
---------------调用方法--------------
领取工具:钻机
工作结束,请先脱掉工作服
--------------环绕增强结束---------------
异常抛出增强:
import org.springframework.aop.ThrowsAdvice;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import java.lang.reflect.Method; public class Main{
public static void main(String[] args) throws Exception {
//2、下面使用Spring的xml配置实例化
ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
//work3带环绕增强
Worker worker3=(Worker)ctx.getBean("worker3");
System.out.println("worker3进入工作:");
worker3.getTool("锤子");
}
} interface Worker {
void getTool(String tool);
void digSomething(String type);
void initWork();
} class DigWorker implements Worker{ @Override
public void getTool(String tool) {
System.out.println("---------------调用方法--------------");
System.out.println("领取工具:"+tool);
throw new RuntimeException("运行异常");
} @Override
public void digSomething(String type) {
System.out.println("---------------调用方法--------------");
System.out.println("开始卖力挖取:"+type); } @Override
public void initWork() {
System.out.println("生成一个DigWorker实例");
}
} class WeaningThrowAdvice implements ThrowsAdvice {
public void afterThrowing(Method method, Object[] args, Object target, Exception ex) throws Throwable {
System.out.println("--------------------");
System.out.println("method:"+method.getName());
System.out.println("抛出异常"+ex.getMessage());
System.out.println("成功回滚事务");
}
}
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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<!-- 要进行增强的目标 -->
<bean id="target" class="com.company.DigWorker" init-method="initWork"/> <!-- 异常抛出增强的方法 -->
<bean id="throwAdvice" class="com.company.WeaningThrowAdvice" /> <!--设置异常抛出增强方法 proxyTargetClass="true",使用CgLib代理-->
<bean id="worker3" class="org.springframework.aop.framework.ProxyFactoryBean"
p:interceptorNames="throwAdvice"
p:target-ref="target"
p:proxyTargetClass="true"/>
</beans>
Result:
生成一个DigWorker实例
worker3进入工作:
---------------调用方法--------------
领取工具:锤子
Exception in thread "main" java.lang.reflect.UndeclaredThrowableException
at com.company.DigWorker$$EnhancerBySpringCGLIB$$b3caca85.getTool(<generated>)
at com.company.Main.main(Main.java:18)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Caused by: java.lang.IllegalAccessException: Class org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor can not access a member of class com.company.WeaningThrowAdvice with modifiers "public"
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)
at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288)
at java.lang.reflect.Method.invoke(Method.java:491)
at org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor.invokeHandlerMethod(ThrowsAdviceInterceptor.java:145)
at org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor.invoke(ThrowsAdviceInterceptor.java:130)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:656)
http://blog.csdn.net/icarus_wang/article/details/51737474
http://www.kancloud.cn/evankaka/springlearning/119668
AOP 增强方法的更多相关文章
- Spring学习之Aop的各种增强方法
AspectJ允许使用注解用于定义切面.切入点和增强处理,而Spring框架则可以识别并根据这些注解来生成AOP代理.Spring只是使用了和AspectJ 5一样的注解,但并没有使用AspectJ的 ...
- spring5 源码深度解析----- AOP目标方法和增强方法的执行(100%理解AOP)
上一篇博文中我们讲了代理类的生成,这一篇主要讲解剩下的部分,当代理类调用时,目标方法和代理方法是如何执行的,我们还是接着上篇的ReflectiveMethodInvocation类Proceed方法来 ...
- 使用spring:aop中修改增强方法中的参数
大家都知道,在增强方法中,使用jp.getArgs()[index]可以获取传进来的参数,但是参数传进来之后,怎么改变它的值呢? 因为jp.getArgs()[index]获取到的只是数据的备份,所以 ...
- spring源码-aop增强-5.2
一.aop增强就是针对于不同的切面进行的相关增强,目的当然是更好的支持相关应用和解耦. 二.默认的aop增强类有AspectJMethodBeforeAdvice.AspectJMethodBefor ...
- AOP获取方法注解实现动态切换数据源
AOP获取方法注解实现动态切换数据源(以下方式尚未经过测试,仅提供思路) ------ 自定义一个用于切换数据源的注解: package com.xxx.annotation; import org. ...
- Spring AOP增强(Advice)
Sring AOP通过PointCut来指定在那些类的那些方法上织入横切逻辑,通过Advice来指定在切点上具体做什么事情.如方法前做什么,方法后做什么,抛出异常做什么. Spring中有两种方式定义 ...
- JS实现AOP拦截方法调用
//JS实现AOP拦截方法调用function jsAOP(obj,handlers) { if(typeof obj == 'function'){ obj = obj.prot ...
- 【Eclipse】_Eclipse自动补全增强方法 & 常用快捷键
一,Eclipse自动补全增强方法 在Eclipse中,从Window -> preferences -> Java -> Editor -> Content assist - ...
- AOP记录方法的执行时间
作用AOP监控方法的运行时间如下: @Component @Aspect public class LogAop { private Logger log = LoggerFactory.getLog ...
随机推荐
- web基础----->readonly与disabled的区别
readonly和Disabled是用在表单中的两个属性,它们都能够做到使用户不能够更改表单域中的内容.但是它们之间有着微小的差别,今天我们通过案例来学习一下. readonly和Disabled的区 ...
- 【WebService】Stax的基本操作基于游标
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <book ...
- MarkDownPad2 key
MarkDownPad2 key : Soar360@live.com GBPduHjWfJU1mZqcPM3BikjYKF6xKhlKIys3i1MU2eJHqWGImDHzWdD6xhMNLGVp ...
- linux awk时间计算脚本
在linux如果计划时间是个麻烦事, 用awk脚本如下 BEGIN {FS=":";OFS=":"} {total_seconds=total_seconds+ ...
- java反射(一)
在JDK中,主要由以下类实现java反射机制:Class类:代表一个类,Filed类:代表类的成员变量,Method类:代表类的方法,Constructor类:代表类的构造方法,Array类:提供平了 ...
- 下载组件Jspsmartupload中文乱码解决办法
先用jdgui反编译jar包,得到源码,然后将源码拷贝到myeclipse中,注意路径是按照源码的路径 打开默认会有错误提示,稍微改改就解决了 1,打开“ SmartUpload.java ”,查 ...
- 修改Docker默认存储位置的方法
在日常使用中由于我们的根目录通常都比较小,如果想大量存储容器镜像的话很容易导致根目录写满 docker 默认的数据目录是/var/lib/docker 我们想要移动数据目录可以按照下面说明操作即可. ...
- Spring 体系结构
https://www.w3cschool.cn/wkspring/dcu91icn.html 体系结构 Spring 有可能成为所有企业应用程序的一站式服务点,然而,Spring 是模块化的,允许你 ...
- Kafka Producer接口
参考, https://cwiki.apache.org/confluence/display/KAFKA/0.8.0+Producer+Example http://kafka.apache.org ...
- Docker+Jenkins_自动化持续集成环境搭建
前一篇文章里已经在内网环境搭建好docker 详见:https://www.cnblogs.com/befer/p/9107503.html, 现在接着搭建一个Docker+Jenkins的集成环境 ...