想说写一个系列,又不敢说写一个系列,害怕只有开头,却没有结尾。但不管怎么样,这篇还是要写下来,不然,就连开头都没有了。 这篇打算将两种实现AOP的技术的hello world写一下。 我们知道,Java实现AOP,一般采用两种技术:
- 使用JDK的动态代理,在代理类中拦截方法的调用,然后做些手脚
- 使用类似cglib之类的工具,将AOP的代码在编译期“织入”进去,就是修改字节码。(更深的我也不知道了……)
一、先说使用动态代理的。
- Java限制被代理的的类必须实现一个接口。(因为代理类也去实现这个接口,而方法的调用是通过实现接口来实现多态的。)
public interface TagetService {
void doSomething();
}
- 再是我们要代理的目标类,即要用aop拦截的方法。
public class TagetServiceImpl implements TagetService {
/**
* 需要被拦截的方法
*/
@Override
public void doSomething() {
System.out.println("doing something.");
}
}
- 然后我们就要编写我们自己的aop逻辑了。实现InvocationHandler接口,在invoke方法中写自己的逻辑代码。
public class TargetServiceInvocationHandler implements InvocationHandler {
/**
* 代理的目标对象
*/
private Object target;
public TargetServiceInvocationHandler(Object target) {
this.target = target;
}
/**
* 拦截方法调用
*
* @param proxy 代理
* @param method 方法
* @param args 参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before do something.");
Object result = method.invoke(target, args);
System.out.println("after do something.");
return result;
}
}
- 万事具备,组装起来,测试一下,(Spring AOP是不是帮我们优雅的组装了一下下?下一篇就研究一下他)
public class Test {
public static void main(String[] args) throws IllegalAccessException, InstantiationException {
// service 实例
TagetService instance = TagetServiceImpl.class.newInstance();
// service 代理的实例
TagetService tagetServiceProxy = (TagetService) Proxy.newProxyInstance(instance.getClass().getClassLoader(),
instance.getClass().getInterfaces(),
new TargetServiceInvocationHandler(instance));
// 用代理的实例调用方法, 即会被handler拦截
tagetServiceProxy.doSomething();
}
}
二、再来cglib的
- 这回被拦截的类不需要实现接口了
public class TargetService {
public void doSomething() {
System.out.println("do something.");
}
}
- 通过实现cglig的MethodInterceptor接口,在intercept方法中实现我们的aop的逻辑
public class TargetServiceInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("before do something.");
Object result = proxy.invokeSuper(obj, args);
System.out.println("after do something.");
return result;
}
}
- 组装起来测试一下下
public class Test {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(TargetService.class);
enhancer.setCallback(new TargetServiceInterceptor());
TargetService targetService = (TargetService) enhancer.create();
targetService.doSomething();
}
}