看透Spring AOP

工作原因需要用到一个代理,首选Spring Aop ,很久没用了,今天翻了下文档看了下源码,发现看文档容易晕,看源码结构清晰明了,Advice,PointCut,Advisor泾渭分明,ProxyFactoryBean总控。
Target:主角,目的就是生成target的代理对象。
Advice:抛弃概念简单理解就是你要插入target的执行代码。
PointCut:就是你要在target文件的哪个方法哪个位置插入,之前还是之后。
Advisor:用来整合Advice与PointCut。
Spring Aop复杂在对于前四者再加上Interceptor的封装,对这四者的装饰封装衍生出了好多类,而实际上就是Proxy.newProxyInstance()罢了(对于非接口当然是耳熟能详的cglib),接下来用JDK动态代理来模拟一下,不想写那么多类了,就Advice植入Target吧,其他硬编码了。
advice接口及两个实现:

package cn.easyweb.aop;

import java.lang.reflect.InvocationHandler;

public interface Advice extends InvocationHandler{
public Object getTarget();
}

package cn.easyweb.aop;

import java.lang.reflect.Method;

public class BeforeAdvice implements Advice{

public Object target;

public BeforeAdvice(Object target){
this.target = target;
}


public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("before....");
method.invoke(target, args);
return null;
}


public Object getTarget() {
return target;
}

}
package cn.easyweb.aop;

import java.lang.reflect.Method;

public class AfterAdvice implements Advice{

public Object target;

public AfterAdvice(Object target){
this.target = target;
}

public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
method.invoke(target, args);
System.out.println("after.....");
return null;
}

public Object getTarget() {
return target;
}

}

主控类EasyProxy :

package cn.easyweb.aop;


public class EasyProxy {

public Advice advice;

public Object createProxy(Advice advice){
this.advice = advice;
return new AopFactory().getObject(advice.getTarget(), advice);
}

}

代理工厂:

package cn.easyweb.aop;

import java.lang.reflect.Proxy;

public class AopFactory {

public Object getObject(Object target,Advice advice){
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), advice);
}

}

需要代理的接口及实现类:

package cn.easyweb.aop;

public interface SourceAssaign {

public void assaign();

}
package cn.easyweb.aop;


public class SimcardAssaign implements SourceAssaign {

public void assaign() {
System.out.println("simcard assaign");
}

}


测试类:

package cn.easyweb.aop;


public class TestAOP {

public static void main(String[] args) {
EasyProxy proxy = new EasyProxy();
Object obj = proxy.createProxy(new BeforeAdvice(new SimcardAssaign()));
SourceAssaign assaign = (SourceAssaign) proxy.createProxy(new AfterAdvice(obj));
assaign.assaign();

}
}

Advice为继承InvocationHandler的接口,抽象个接口用来实现代理链,target简单起见聚合进advice。

aop的应用非常广,除了平时经常见到的事物日志啊这些乱七八糟的控制 以外,前两天看连接池时候突然发现c3p0的也用到了动态代理,连接池产生的connection全部用动态代理产生,好处是每次调用connection.close()时,防止被真正关闭,而是让其回归连接池,当然使用spring的人估计是很难发现这点,这也是用惯了封装框架的弊端啊。

另外个人觉得spring aop之所以强大的原因还是有IOC在支持,除去IOC spring aop无非就是对几个代理点封装的好而已,单独用AspectJ都比这强,但是一加入IOC就真正做到了热插拔,侵入性一下子消失了,所以spring的核心个人觉得还应该是IOC,而不是IOC+AOP。

下次再写一篇spring jdbc的,spring jdbc的设计相当完美,用模版和回调解决jdbc的冗余代码,Rod Johnson太有才了。。。。。。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值