首先我们先来一个简单到不能简单的服务接口:
HelloService.java
package com.jd.www.jpl.service;
public interface HelloService {
public void sayHello();
}
以及实现类
HelloServiceImpl.java
package com.jd.www.jpl.service.impl;
import com.jd.www.jpl.service.HelloService;
public class HelloServiceImpl implements HelloService {
@Override
public void sayHello() {
System.out.println("hello world!!");
}
}
接着创建一个拦截器接口
Interceptor.java
package com.jd.www.jpl.common.aop.proxy;
public interface Interceptor {
// 前置通知
void before();
// 是否采用环绕通知
boolean useAround();
// 环绕通知
Object around(Object target, Method method, Object[] args)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException;
// 事后方法
void after();
// 异常返回方法
void afterThrowing();
// 正常返回方法
void afterReturning();
}
依据这个接口,可以给出一个很简单的实现
MyInterceptor.java
package com.jd.www.jpl.common.aop.proxy.impl;
import com.jd.www.jpl.common.aop.proxy.Interceptor;
public class MyInterceptor implements Interceptor {
@Override
public void before() {
System.out.println("事前通知");
}
@Override
public boolean useAround() {
return true;
}
@Override
public Object around(Object target, Method method, Object[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
System.out.println("环绕通知before");
Object o = method.invoke(target,args);
System.out.println("环绕通知after");
return o;
}
@Override
public void after() {
System.out.println("事后通知");
}
@Override
public void afterThrowing() {
System.out.println("异常返回通知");
}
@Override
public void afterReturning() {
System.out.println("正常返回通知");
}
}
如果用proxy去调用方法,约定如下:
1、首先调用拦截器的before方法;
2、如果拦截器的useAround方法,返回为true,则执行拦截器的around方法,不执行target对象原有的sayHello方法;
3、无论结果如何都会执行拦截器的after方法;
4、如果around方法有异常或者原有的target对象的sayHello方法有异常,则执行拦截器的afterThrowing方法,否则执行afterReturning方法。
好了,为了更好的说明,我们来个流程图。
流程图对应的ProxyBean
package com.jd.www.jpl.common.aop.proxy.impl;
public class ProxyBean implements InvocationHandler {
private Object target;
private Interceptor interceptor;
public static Object getProxyBean(Object target, Interceptor interceptor){
ProxyBean proxyBean = new ProxyBean();
proxyBean.target = target;
proxyBean.interceptor = interceptor;
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),proxyBean);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
boolean e = false;
Object ret = null;
MyInterceptor myInterceptor = new MyInterceptor();
myInterceptor.before();
try {
if(interceptor.useAround()){
ret = myInterceptor.around(target,method,args);
}else {
ret = method.invoke(target,args);
}
} catch (InvocationTargetException | IllegalAccessException | IllegalArgumentException ex) {
e = true;
}
myInterceptor.after();
if(e){
myInterceptor.afterThrowing();
}else{
myInterceptor.afterReturning();
return ret;
}
return null;
}
}
创建测试用例
SpringAopTest.java
package com.jd.jmq.consumer;
import com.jd.www.jpl.common.aop.proxy.impl.MyInterceptor;
import com.jd.www.jpl.common.aop.proxy.impl.ProxyBean;
import com.jd.www.jpl.service.HelloService;
import com.jd.www.jpl.service.impl.HelloServiceImpl;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath*:spring/spring-consumer.xml"})
public class SpringAopTest {
@Test
public void testAop(){
HelloService helloService = new HelloServiceImpl();
HelloService proxy = (HelloService) ProxyBean.getProxyBean(helloService,new MyInterceptor());
proxy.sayHello();
}
}
运行结果:
结果
网友评论