Spring AOP 创建增强类
AOP联盟为增强定义了org.aopalliance.aop.Advice接口,Spring支持5种类型的增强:
package com.yyq.advice;
public interface Waiter {
void greetTo(String name);
void serveTo(String name);
}
NaiveWaiter服务类:
package com.yyq.advice;
public class NaiveWaiter implements Waiter {
@Override
public void greetTo(String name) {
System.out.println("greet to " + name + "...");
}
@Override
public void serveTo(String name) {
System.out.println("serving to " + name + "...");
}
}
前置增强实现类:
package com.yyq.advice;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class GreetingBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
String clientName = (String) objects[0];
System.out.println("How are you ! Mr." + clientName + ".");
}
}
测试方法:
@Test
public void testBeforeAdvice(){
Waiter target = new NaiveWaiter();
BeforeAdvice advice = new GreetingBeforeAdvice();
ProxyFactory pf = new ProxyFactory(); //Spring提供的代理工厂
pf.setTarget(target); //设置代理目标
pf.addAdvice(advice);
Waiter proxy = (Waiter)pf.getProxy(); //生成代理实例
proxy.greetTo("John");
proxy.serveTo("Tom");
}
<bean id="greetingAdvice" class="com.yyq.advice.GreetingBeforeAdvice"/>
<bean id="target" class="com.yyq.advice.NaiveWaiter"/> <bean id="waiter1" class="org.springframework.aop.framework.ProxyFactoryBean"
p:proxyInterfaces="com.yyq.advice.Waiter"
p:interceptorNames="greetingAdvice"
p:target-ref="target"/>
ProxyFactoryBean 是FactoryBean接口的实现类。
@Test
public void testBeforeAdvice2(){
String configPath = "com\\yyq\\advice\\beans.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath);
Waiter waiter = (Waiter)ctx.getBean("waiter1");
waiter.greetTo("Joe");
}
package com.yyq.advice;
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
public class GreetingAfterAdvice implements AfterReturningAdvice {
@Override
public void afterReturning(Object o, Method method, Object[] objects, Object o2) throws Throwable {
System.out.println("Please enjoy yourself.");
}
}
在beans.xml文件添加后置增强:
<bean id="greetingBefore" class="com.yyq.advice.GreetingBeforeAdvice"/>
<bean id="greetingAfter" class="com.yyq.advice.GreetingAfterAdvice"/>
<bean id="waiter2" class="org.springframework.aop.framework.ProxyFactoryBean"
p:proxyInterfaces="com.yyq.advice.Waiter"
p:interceptorNames="greetingBefore,greetingAfter"
p:target-ref="target"/>
测试方法:
@Test
public void testBeforeAndAfterAdvice(){
String configPath = "com\\yyq\\advice\\beans.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath);
Waiter waiter = (Waiter)ctx.getBean("waiter2");
waiter.greetTo("Joe");
}
package com.yyq.advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class GreetingInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
Object[] args = methodInvocation.getArguments();
String clientName = (String) args[0];
System.out.println("Hi,Mr " + clientName + ".");
Object obj = methodInvocation.proceed();
System.out.println("Please enjoy yourself~");
return obj;
}
}
Spring 直接使用AOP联盟所定义的MethodInterceptor作为环绕增强的接口。该接口拥有唯一的接口方法 Object invoke(MethodInvocation invocation), MethodInvocation不但封装目标方法及其入参数组,还封装了目标方法所在的实例对象,通过MethodInvocation的getArguments()可以获取目标方法的入参数组,通过proceed()反射调用目标实例相应的方法。
<bean id="greetingAround" class="com.yyq.advice.GreetingInterceptor"/>
<bean id="waiter3" class="org.springframework.aop.framework.ProxyFactoryBean"
p:proxyInterfaces="com.yyq.advice.Waiter"
p:interceptorNames="greetingAround"
p:target-ref="target"/>
测试方法:
@Test
public void testAroundAdvice(){
String configPath = "com\\yyq\\advice\\beans.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath);
Waiter waiter = (Waiter)ctx.getBean("waiter3");
waiter.greetTo("Joe");
}
package com.yyq.advice;
public class Forum {
private int forumId;
public int getForumId() {
return forumId;
}
public void setForumId(int forumId) {
this.forumId = forumId;
}
}
ForumService业务类:
package com.yyq.advice;
import java.sql.SQLException;
public class ForumService {
public void removeForum(int forumId){
System.out.println("removeForum....");
throw new RuntimeException("运行异常");
}
public void updateForum(Forum forum)throws Exception{
System.out.println("updateForum");
throw new SQLException("数据更新操作异常。");
}
}
TransactionManager异常抛出增强实现类:
package com.yyq.advice;
import org.springframework.aop.ThrowsAdvice;
import java.lang.reflect.Method;
public class TransactionManager 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("成功回滚事务。");
}
}
<bean id="transactionManager" class="com.yyq.advice.TransactionManager"/>
<bean id="forumServiceTarget" class="com.yyq.advice.ForumService"/>
<bean id="forumService" class="org.springframework.aop.framework.ProxyFactoryBean"
p:interceptorNames="transactionManager"
p:target-ref="forumServiceTarget"
p:proxyTargetClass="true"/>
测试方法:
@Test
public void testThrowsAdvice(){
String configPath = "com\\yyq\\advice\\beans.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath);
ForumService fs = (ForumService)ctx.getBean("forumService");
try{
fs.removeForum(10);
} catch (Exception e) {}
try{
fs.updateForum(new Forum());
} catch (Exception e) {}
}
package com.yyq.advice;
public interface Monitorable {
void setMonitorActive(boolean active);
}
ControllablePerformanceMonitor 为引介增强实现类:
package com.yyq.advice;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.support.DelegatingIntroductionInterceptor;
public class ControllablePerformanceMonitor extends DelegatingIntroductionInterceptor implements Monitorable {
private ThreadLocal<Boolean> MonitorStatusMap = new ThreadLocal<Boolean>();
@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()) {
PerformanceMonitor.begin(mi.getClass().getName() + "." + mi.getMethod().getName());
obj = super.invoke(mi);
PerformanceMonitor.end();
} else {
obj = super.invoke(mi);
}
return obj;
}
}
PerformanceMonitor监视类:
package com.yyq.advice;
public class PerformanceMonitor {
private static ThreadLocal<MethodPerformance> performanceRecord = new ThreadLocal<MethodPerformance>();
public static void begin(String method) {
System.out.println("begin monitor...");
MethodPerformance mp = new MethodPerformance(method);
performanceRecord.set(mp);
}
public static void end(){
System.out.println("end monitor...");
MethodPerformance mp = performanceRecord.get();
mp.printPerformance();
}
}
MethodPerformance记录性能信息:
public class MethodPerformance {
private long begin;
private long end;
private String serviceMethod;
public MethodPerformance(String serviceMethod){
this.serviceMethod = serviceMethod;
this.begin = System.currentTimeMillis();
}
public void printPerformance(){
end = System.currentTimeMillis();
long elapse = end - begin;
System.out.println(serviceMethod + "花费" + elapse + "毫秒。");
}
}
在beans.xml文件添加引介增强:
<bean id="pmonitor" class="com.yyq.advice.ControllablePerformanceMonitor"/>
<bean id="forumServiceImplTarget" class="com.yyq.advice.ForumServiceImpl"/>
<bean id="forumService2" class="org.springframework.aop.framework.ProxyFactoryBean"
p:interfaces="com.yyq.advice.Monitorable"
p:interceptorNames="pmonitor"
p:target-ref="forumServiceImplTarget"
p:proxyTargetClass="true"/>
@Test
public void testIntroduce(){
String configPath = "com\\yyq\\advice\\beans.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath);
ForumServiceImpl forumServiceImpl = (ForumServiceImpl)ctx.getBean("forumService2");
forumServiceImpl.removeForum(23);
forumServiceImpl.removeTopic(1023);
Monitorable monitorable = (Monitorable)forumServiceImpl;
monitorable.setMonitorActive(true);
forumServiceImpl.removeForum(22);
forumServiceImpl.removeTopic(1023);
}
Spring AOP 创建增强类的更多相关文章
- (spring-第17回【AOP基础篇】) 创建增强类
一. 增强类包含的信息: a) 横切逻辑(插入的具体代码) b) 部分连接点信息(在方法的哪个位置插入代码,比如方法前.方法后等). 二. 增强的类型 每一种增强有一个需要实现的增强类 ...
- Spring aop:decare-parent 为类增加新的方法
Spring aop:decare-parent 为类增加新的方法: 使用XML配置的方式: XML: <?xml version="1.0" encoding=" ...
- Spring AOP切面变成——创建增强类
说明 Spring使用增强类定义横向逻辑,同时Spring只支持方法连接点,增量类还包含在方法的哪一点添加横切代码的方位信息.所以增强既包含横向逻辑,又包含部分连接点的信息. 类型 按着增强在目标类方 ...
- Spring aop——前置增强和后置增强 使用注解Aspect和非侵入式配置
AspectJ是一个面向切面的框架,它扩展了java语言,定义了AOP语法,能够在编译期提供代码的织入,所以它有一个专门的编译器用来生成遵守字节码字节编码规范的Class文件 确保使用jdk为5.0以 ...
- 阿里四面:你知道Spring AOP创建Proxy的过程吗?
Spring在程序运行期,就能帮助我们把切面中的代码织入Bean的方法内,让开发者能无感知地在容器对象方法前后随心添加相应处理逻辑,所以AOP其实就是个代理模式. 但凡是代理,由于代码不可直接阅读,也 ...
- spring aop无法拦截类内部的方法调用
1.概念 拦截器的实现原理就是动态代理,实现AOP机制.Spring 的代理实现有两种:一是基于 JDK Dynamic Proxy 技术而实现的:二是基于 CGLIB 技术而实现的.如果目标对象实现 ...
- Spring AOP 创建切面
增强被织入到目标类的所有方法中,但是如果需要有选择性的织入到目标类某些特定的方法中时,就需要使用切点进行目标连接点的定位.增强提供了连接点方位信息:如织入到方法前面.后面等,而切点进一步描述织 ...
- Spring AOP(基于代理类的AOP实现)
#基于代理类的AOP实现:step1: 1 package com.sjl.factorybean; /**切面类*/ import org.aopalliance.intercept.MethodI ...
- Spring AOP创建Throwdvice实例
1.异常发生的时候,通知某个服务对象做处理 2.实现throwsAdvice接口 接口实现: public interface IHello { public void sayHello(String ...
随机推荐
- Eigen库实现简单的旋转、平移操作
本来课程要求用GUI界面来实现Eigen的旋转.平移操作的,但是接触GUI编程时间太短,虽然要求很简单,但是做了几天还是没有完成.就把命令行下面的简单的贴一下吧. main.cpp #include ...
- android开发 无预览定时拍照
demo实现功能: 打开主页面自动启动定时拍照,10s拍一次. 注意事项,初始化摄像头之后不能立即拍照,否则无效,必须等待几秒后才能拍.这里用的是Handler进行延时处理拍照消息的. package ...
- Python编码设置
系统编码顺序: 1, a.encode(sys.stdout.encoding) 2, a.encode(default_string) sys.stdout.encoding里的值可以用环境变量PY ...
- IntelliJ IDEA 15激活
1.按正常的安装方法安装好IDEA : 2.使用iteblog提供的License server(服务器地址为http://www.iteblog.com/idea/key.php)进行注册 ---- ...
- 《我是一只IT小小鸟》阅读笔记
<我是一只IT小小鸟>,这本书对我来说,有可能我现在并不懂得那其中的道理,但是,我觉得它写的很好,很现在的我很相似,但是在里面,我看到了他们都在说,一开始可能并不对IT这门课有很深的见解, ...
- Codeforces Round #353 (Div. 2) D. Tree Construction 二叉搜索树
题目链接: http://codeforces.com/contest/675/problem/D 题意: 给你一系列点,叫你构造二叉搜索树,并且按输入顺序输出除根节点以外的所有节点的父亲. 题解: ...
- web开发--文档下载
GOOGLE在线文档下载地址分享(GOOGLE的文档地址暂不能用了,会放在其它位置..) GOOGLE的在线文档功能好象挂掉了...等找个其它存放的位置把这些文档再上传上去... 存在GOOGLE里面 ...
- 一个关于ExtJS4具体控件的详细教程
发现一遍介绍ExtJS控件介绍的比较好的系列文章,在此做总结 ExtJs4 笔记(1) ExtJs大比拼JQuery:Dom文档操作 ExtJs4 笔记(2) ExtJs对js基本语法扩展支持 Ext ...
- 【POJ】【3680】Intervals
网络流/费用流 引用下题解: lyd: 首先把区间端点离散化,设原来的数值i离散化后的标号是c[i].这样离散化之后,整个数轴被分成了一段段小区间. 1.建立S和T,从S到离散化后的第一个点连容量K, ...
- Codeforces Round #283 (Div. 2)
A:暴力弄就好,怎么方便怎么来. B:我们知道最多加10次, 然后每次加1后我们求能移动的最小值,大概O(N)的效率. #include<bits/stdc++.h> using name ...