通常对于spring的AOP功能,大家都能说出一二来,但是AOP技术到底是怎么实现的呢?
分为jdk自动的动态代理方式和cglib实现动态代理这两种方式,那下面就来具体看看怎么实现的。
一,看看jdk的动态代理方式:
1,用到jdk动态代理的时候,目标类(HcieServiceImpl)必须有实现接口(HcieService)。
package cn.china.hu;
public class HcieServiceImpl implements HcieService { //必须实现接口
private String user;
public HcieServiceImpl(String str) {
this.user = str;
}
@Override
public void save(String str) {
System.out.println("save()..."+str);
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
}
2, 动态代理类必须实现InvocationHandler这个接口,并实现invoke()方法。
有一个创建代理实例的方法createProxyInstance(),Proxy实例化方法的参数必须有类加载器和实现的接口。
package cn.china.hu;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* JDK的Proxy实现AOP的功能
*/
public class JDKProxyFactory implements InvocationHandler{
private Object target;
public Object createProxyInstance(Object target){
this.target = target;
//create proxy
Object obj = Proxy.newProxyInstance(
this.target.getClass().getClassLoader(), //目标类加载器
this.target.getClass().getInterfaces(), //目标类实现的接口
this
);
return obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
//环绕通知
HcieServiceImpl hcie = (HcieServiceImpl) this.target;
Object result = null;
if (hcie.getUser() != null) {
try {
//前置通知 ...advice
System.out.println("前置通知");
result = method.invoke(target, args);
//后置通知
} catch (Exception e) {
// 例外通知
}finally{
//最终通知
System.out.println("最终通知");
}
}
return result;
}
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
}
二,看看cglib实现动态代理方式:
1,用到cglib实现动态代理的时候,目标类(HcieServiceImpl2)没有实现接口。
package cn.china.hu;
public class HcieServiceImpl2 { //用cglib处理没有实现接口的
private String user;
public HcieServiceImpl2() {} //空参的构造函数,在cglib中superClass的时候需要用到
public HcieServiceImpl2(String str) {//带惨的构造函数
this.user = str;
}
public void save(String str) {
System.out.println("save方法..."+str);
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
}
2,动态代理类必须实现MethodInterceptor这个接口,并实现intercept()方法。
有一个创建代理实例的方法creaProxyInstace(),Enhancer对象来创建代理对象。
package cn.china.hu;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* 用cglib的方式实现AOP的功能
*/
public class CGlibProxyFactory implements MethodInterceptor {
private Object target;
//create proxy
public Object creaProxyInstace(Object target){
this.target = target;
Enhancer enhancer = new Enhancer(); //用到这个Enhancer对象,jdk中用的Proxy对象
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
//环绕通知
HcieServiceImpl2 hcie = (HcieServiceImpl2) this.target;
Object result = null;
if (hcie.getUser() != null) {
try {
//前置通知 ...advice
System.out.println("前置通知");
result = method.invoke(target, args);
//后置通知
} catch (Exception e) {
// 例外通知
}finally{
//最终通知
System.out.println("最终通知");
}
}
return result;
}
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
}
三,测试类:
public class AOPtest {
@Test
public void test() {
//JDKProxyFactory
JDKProxyFactory proxy = new JDKProxyFactory();
HcieService service = (HcieService)proxy.createProxyInstance(new HcieServiceImpl("a"));
service.save("b");
//CGlibProxyFactory
CGlibProxyFactory cgliab= new CGlibProxyFactory();
HcieServiceImpl2 lib = (HcieServiceImpl2) cgliab.creaProxyInstace(new HcieServiceImpl2("aaa"));
lib.save("bbb");
}
}
四,两者的对比到此为止吧,后续有时间再多补充补充,共同学习!