一、AOP是什么?
大家都知道这是什么,“面向切面编程”(Aspect-Oriented Programming)。此处对于,定义以及概念就不在赘述,请自行查阅。
二、为什么需要AOP?
为什么需要AOP?换句话说,AOP帮我们解决了什么问题呢?
大家熟知的JDBC代码块,开始连接数据库,最后关闭数据库连接。这样一个过程,大家需要重复的写拿连接,关连接的代码。
因此,我们只需要中间的那一段代码就可以了,两端的完全可以与之分离开来。再如性能监控,权限控制,日志记录等等。
以上的情况下,显然我们需要在这个点上横向的做一些操作。这不仅简化代码,提高开发效率,
也将上述所说的“大家都做的”那部分代码从核心的业务逻辑中剥离出来进行解耦,更专注于业务逻辑的部分。
三、如何实现?
定义以下接口:
public interface Worker {
void doJob(String doing);
}
实现类:
public class CoderImpl implements Worker {
@Override
public void doJob(String doing) {
System.out.println("Your job is" + doing);
}
}
直接写在实现类里:
public class CoderImpl implements Worker {
@Override
public void doJob(String doing) {
before();
System.out.println("Your job is" + doing);
after();
}
private void before(){
System.out.println("working before...");
}
private void after(){
System.out.println("working after...");
}
}
如上写死代码显然不是好的办法,所以可以通过以下解决:
· 静态代理
· JDK动态代理
· CGLib动态代理
如上,通过静态代理实现,当出现码农工,农民工,搬砖工==的时候会有越来越多的,代理类出现,这不是一个好的idea。
所以需要一个代理类就够了,这时候,JDK提供的动态代理是不错的。
但是JDK提供的动态代理是基于有接口的实现类,当出现无实现接口的类时就不再适用了。
所以,CGLib则提供了这方面的实现。
静态代理实现:
public class CoderProxy implements Worker{
private CoderImpl coderImpl;
public CoderProxy(CoderImpl coderImpl){
this.coderImpl = coderImpl;
}
@Override
public void doJob(String doing) {
before();
coderImpl.doJob(doing);
after();
}
private void before(){
System.out.println("working before...");
}
private void after(){
System.out.println("working after...");
}
}
写一个test:
public class Test {
public static void main(String[] args) {
CoderProxy coderProxy = new CoderProxy(new CoderImpl());
coderProxy.doJob("写代码");
}
}
结果如下:
working before…
Your job is:写代码
working after…
JDK动态代理实现:
public class JDKDynamicProxy implements InvocationHandler {
private Object target;
public JDKDynamicProxy(Object target){
this.target = target;
}
@SuppressWarnings("unchecked")
public <T> T getProxy(){
return (T) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
//注意此处的第一个参数并不是proxy
Object object = method.invoke(target, args);
after();
return object;
}
private void before(){
System.out.println("working before...");
}
private void after(){
System.out.println("working after...");
}
}
写一个test的main方法:
public static void main(String[] args) {
Worker coder = new JDKDynamicProxy(new CoderImpl()).getProxy();
coder.doJob("写代码");
}
结果为:
working before…
Your job is:写代码
working after…
CGLib代理实现:
需要使用CGLib jar包
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CGLibProxy implements MethodInterceptor{
//使用单例模式
private static CGLibProxy instance = new CGLibProxy();
private CGLibProxy(){}
public static CGLibProxy getInstance(){
return instance;
}
@SuppressWarnings("unchecked")
public <T> T getProxy(Class<T> cls){
return (T)Enhancer.create(cls, this);
}
@Override
public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable {
before();
Object obj = proxy.invokeSuper(target, args);
after();
return obj;
}
private void before(){
System.out.println("working before...");
}
private void after(){
System.out.println("working after...");
}
}
测试一下:
public static void main(String[] args) {
Worker coder = CGLibProxy.getInstance().getProxy(CoderImpl.class);
coder.doJob("write code!");
}
未完待续……
参考:《架构探险:从零开始写Java Web框架》(黄勇 著)