现在的位置: 首页 > 综合 > 正文

AOP实现–JDK中的动态代理和cglib代理

2018年05月28日 ⁄ 综合 ⁄ 共 3918字 ⁄ 字号 评论关闭

java.lang.reflect  Interface
InvocationHandler

可参考http://www.gznc.edu.cn/yxsz/jjglxy/book/Java_api/java/lang/reflect/InvocationHandler.html

http://www.gznc.edu.cn/yxsz/jjglxy/book/Java_api/java/lang/reflect/Proxy.html

invocation是“调用”的意思。这个类可以让我们在JVM调用某个类的方法时动态的为些方法做些什么事.InvocationHandler接口把我们的代理对象和被代理对象解耦了.动态代理类可以对任何实现某一接口的类进行功能性的增强。

关于Method对象的invoke方法,根据java的反射机制可以获得某个对象的某个方法,也可以动态调用,假设已经获取了这个方法method.那么method.invoke(owner,args)就是动态调用,owner表示方法所属的对象,args为Object[]类型的方法参数。

接口InvocationHandler的方法

public Object invoke(Object proxy, Method method, Object[] args) throws
Throwable

proxy:在其上调用方法的代理实例(Proxy类型的对象)。

method:对应于在代理实例上调用的接口方法的 Method 实例。。

args:为方法的参数

复制代码
 1 package proxy;
2
3 import java.lang.reflect.InvocationHandler;
4 import java.lang.reflect.Method;
5 import java.lang.reflect.Proxy;
6 public class DynProxy implements InvocationHandler{
7 private Object src;//被代理对象
8 //bind为自定义方法,将src绑定到某个代理中
9 //把当前对象(实现了InvocationHandler接口)传递给代理对象
10 //返回代理对象
11 public Object bind(Object src){
12 this.src=src;
13 Object proxy=Proxy.newProxyInstance(
14 src.getClass().getClassLoader(),//被代理对象的类加载器
15 src.getClass().getInterfaces(),//被代理对象实现的接口们,代理对象可以实现全部接口
16 this //当前对象(实现了InvocationHandler接口) 回调,拦截到一个方法后可以触发哪个类中的哪个方法。
17 );
18 //返回的是一个带有代理类的指定调用处理程序的代理实例,它由指定的类加载器定义,并实现指定的接口
19 return proxy;
20 }
21 //InvocationHandler接口方法
22 //src(目标对象)中的每个方法会被此方法送去JVM调用,也就是说,src的方法只能通过此方法调用
23 //此方法不能自己调用
24 public Object invoke(Object proxy, Method method, Object[] args)
25 throws Throwable {
26 // TODO Auto-generated method stub
27 System.out.println(method.getName()+"调用前");
28 Object result=method.invoke(src, args);
29 return result;
30 }
31 public static void main(String[] args) {
32 Login src=new Login(); //被代理对象
33 DynProxy dp=new DynProxy();
34 ILogin proxy=(ILogin)dp.bind(src); //返回代理对象
35 String username="tazi",password="123";
36 proxy.login(username, password); //在代理实例上调用接口方法
37 }
38 }
复制代码

代理对象实现了目标对象的接口,使用时要用接口来引用代理对象。

以上的代码改个名字更好理解:

复制代码
 1 package com.tazi.aop;
2
3 import java.lang.reflect.InvocationHandler;
4 import java.lang.reflect.Method;
5 import java.lang.reflect.Proxy;
6 //JDK方式的动态代理对象的创建工厂
7 public class JDKProxyFactory implements InvocationHandler{
8 private Object target;//目标对象
9 //创建代理对象的方法
10 //返回的是已经实现了目标对象所有接口的代理对象
11 public Object createProxy(Object target){
12 this.target=target;
13 //以下前两个参数跟目标对象有关
14 //第三个参数是一个包含回调方法(invoke)的对象(实现InvocationHandler接口)
15 return Proxy.newProxyInstance(target.getClass().getClassLoader()
16 , target.getClass().getInterfaces(),this);
17 }
18 //当拦截到目标对象某个方法时的回调方法
19 public Object invoke(Object proxy, Method method, Object[] args)
20 throws Throwable {
21 // TODO Auto-generated method stub
22 System.out.println("方法执行前");
23 Object result=method.invoke(target, args);
24 System.out.println("方法执行后");
25
26 return result;
27 }
28 }
复制代码

测试用例:

 

复制代码
package junit.test;

import static org.junit.Assert.*;

import org.junit.BeforeClass;
import org.junit.Test;



import com.tazi.aop.JDKProxyFactory;
import com.tazi.aop.PersonService;
import com.tazi.aop.PersonServiceBean;

public class ProxyTest {
private static JDKProxyFactory proxyFactory;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
proxyFactory=new JDKProxyFactory();
}
@Test
public void proxy() throws Exception {
PersonService pService=(PersonService)proxyFactory.createProxy(new PersonServiceBean());
pService.save("xxx");
}
}
复制代码

CGLIB实现动态代理

但实际中情况会比较复杂,有可能目标对象没有实现接口。如果没有就不能创建代理对象。此时用到第三方的jar包来创建代理对象。cglib.jar。这时目标对象可以不实现接口。

cglib的实现方式是创建被代理对象的子类,这个子类覆盖了目标对象的所有的非final的所有方法。然后设置回调方法。

复制代码
 1 package com.tazi.aop;
2
3 import java.lang.reflect.Method;
4
5 import net.sf.cglib.proxy.Enhancer;
6 import net.sf.cglib.proxy.MethodInterceptor;
7 import net.sf.cglib.proxy.MethodProxy;
8
9 public class CglibProxyFactory implements MethodInterceptor{
10 private Object target;
11 public Object createProxy(Object target){
12 this.target=target;
13 Enhancer enhancer=new Enhancer();
14 enhancer.setSuperclass(target.getClass());
15 enhancer.setCallback(this);
16 return enhancer.create();
17 }
18 public Object intercept(Object proxy, Method method, Object[] args,
19 MethodProxy methodProxy) throws Throwable {
20 System.out.println("方法执行前00");
21 Object result=method.invoke(target, args);
22 System.out.println("方法执行后00");
23 return result;
24 }
25 }
复制代码

抱歉!评论已关闭.