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 ...
随机推荐
- Node.js 学习(六)Node.js EventEmitter
Node.js 所有的异步 I/O 操作在完成时都会发送一个事件到事件队列. Node.js里面的许多对象都会分发事件:一个net.Server对象会在每次有新连接时分发一个事件, 一个fs.read ...
- Spring MVC 环境搭建(一)
一.建立 JavaWeb 项目 1.建立一个 Java 项目. 2.在项目下新建一个文件夹 webapp (命名可自取,这个目录即是网站根目录),再在该文件夹下新建一个 WEB-INF 文件夹(命名固 ...
- html5之canvas练习
代码地址:github.com/peng666/blogs 在线地址:http://peng666.github.io/blogs/
- Nodejs Express 4.X 中文API 3--- Response篇
相关阅读: Express 4.X API 翻译[一] -- Application篇 Express4.XApi 翻译[二] -- Request篇 Express4.XApi 翻译[三] -- ...
- WPF编程学习——样式
本文目录 1.引言 2.怎样使用样式? 3.内联样式 4.已命名样式 5.元素类型样式 6.编程控制样式 7.触发器 1.引言 样式(Style),主要是用来让元素或内容呈现一定外观的属性.WPF中的 ...
- HDOJ 2152 Fruit(母函数)
Fruit Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- SQLserver分页查询实例
Sqlserver数据库分页查询一直是Sqlserver的短板,闲来无事,想出几种方法,假设有表ARTICLE,字段ID.YEAR...(其他省略),数据53210条(客户真实数据,量不大),分页查询 ...
- c#中的线程一
一.使用线程的理由 1.可以使用线程将代码同其他代码隔离,提高应用程序的可靠性. 2.可以使用线程来简化编码. 3.可以使用线程来实现并发执行 二.基本知识 1.进程与线程:进程作为操作系统执行程序的 ...
- uva 11090
I I U P C 2 0 0 6 Problem G: Going in Cycle!! Input: standard input Output: standard output You are ...
- CPLD VS FPGA
FPGA(Field-Programmable Gate Array),即现场可编程门阵列,它是在PAL.GAL.CPLD等可编程器件的基础上进一步发展的产物.它是作为专用集成电路(ASIC)领域中的 ...