论坛首页 Java企业应用论坛

动态代理Proxy的递归

浏览 3469 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-07-29  
由java.lang.reflect.Proxy得到的动态代理类实例依然是一个Proxy
现在我写两个Handler来实现不同的切面功能: handler_1 和handler_2
看如下代码:
1 接口
public interface IService {

    void foo();
}


2 实现
public class ServiceImpl implements IService{

    public void foo() {
        System.out.println("Business really goes here");
    }

}


3 切面
public class handler_1 implements InvocationHandler {

    private Object stub;

    public handler_1(Object stub) {
        this.stub = stub;
    }

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


public class handler_2 implements InvocationHandler {

    private Object stub;

    public handler_2(Object stub) {
        this.stub = stub;
    }

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


4 客户代码
  public static void main(String[] args) {
        // TODO code application logic here
        ServiceImpl si = new ServiceImpl();
        handler_1 h1 = new handler_1(si);
        handler_2 h2 = new handler_2(si);

        Proxy p1 = (Proxy) Proxy.newProxyInstance(IService.class.getClassLoader(), new Class[]{IService.class}, h1);
        //利用得到的p1代理实例来获取第二个实例,并指定其处理程序为h2
        @SuppressWarnings("static-access")
        Proxy p2 = (Proxy) p1.newProxyInstance(IService.class.getClassLoader(), new Class[]{IService.class}, h2);

        IService service_1 = (IService) p1;
        IService service_2 = (IService) p2;
        service_1.foo();
        service_2.foo();

    }


Guess what,最终得到的这个p_2的动态代理实例到底采用的那个handler切面呢? 是h2的还是h1+h2的?
引用
init:
deps-jar:
Compiling 1 source file to F:\aop\build\classes
compile:
run:
before handler_1
Business really goes here
after handler_1
before handler_2
Business really goes here
after handler_2
成功生成(总时间:0 秒)


可以使用如下方法:
引用
        IService service= (IService) Proxy.newProxyInstance(IService.class.getClassLoader(), new Class[]{IService.class}, h1);
        IService service= (IService) Proxy.newProxyInstance(IService.class.getClassLoader(), new Class[]{IService.class}, service);



   发表时间:2008-07-31  
创意不错, 只是楼主的代码写错了, 没有达到初始目的.


这段是编译不过的.
引用
IService service= (IService) Proxy.newProxyInstance(IService.class.getClassLoader(), new Class[]{IService.class}, h1);
IService service= (IService) Proxy.newProxyInstance(IService.class.getClassLoader(), new Class[]{IService.class}, service);



楼主的main方法和下面的普通使用Proxy的过程是一样的, 所以, 你没有达到你想要的测试效果.
public static void main(String[] args) {   
      ServiceImpl si = new ServiceImpl();  
 
      handler_1 h1 = new handler_1(si);   // 对 new ServiceImpl() 的代理 
      Proxy p1 = (Proxy) Proxy.newProxyInstance(IService.class.getClassLoader(), new Class[]{IService.class}, h1);   
      IService service_1 = (IService) p1;   
      service_1.foo();   
      
      handler_2 h2 = new handler_2(si);  // 还是对 new ServiceImpl() 的代理, 而不是对一个被代理过的对象再次代理. 
      Proxy p2 = (Proxy) Proxy .newProxyInstance(IService.class.getClassLoader(), new Class[]{IService.class}, h2);   
      IService service_2 = (IService) p2;   
      service_2.foo();   
}  



修改过的代码:
	public static void main(String[] args) {
		ServiceImpl si = new ServiceImpl();
		
		handler_1 h1 = new handler_1(si);

		Proxy p1 = (Proxy) Proxy.newProxyInstance(IService.class.getClassLoader(), new Class[] { IService.class }, h1);
		IService service_1 = (IService) p1;
		service_1.foo(); // 一次普通的代理
		
		System.out.println("----------");
		
		handler_2 h2 = new handler_2(service_1); // 对代理生成的代理对象 进行再次代理
		Proxy p2 = (Proxy) Proxy.newProxyInstance(IService.class.getClassLoader(), new Class[] { IService.class }, h2);
		IService service_2 = (IService) p2;
		service_2.foo(); // 代理 代理
	}


测试结果如下:
before handler_1
Business really goes here
after handler_1
----------       // 下面的结果比较搞. 不过也在情理之中.
before handler_2
before handler_1
Business really goes here
after handler_1
after handler_2
0 请登录后投票
   发表时间:2008-07-31  
感谢兄弟纠正,其实俺最后的那段代码就是这个意思,并且是可以执行的。
所谓代理的代理就是如此
但是这样的解决方法比较粗糙,应用开发人员如果想要一次织入多个独立的advice不得不写多次重复的代码,而且执行顺序是写死后不能灵活配置的。所以我打算利用跟Servlet filter或者Spring中InterceptorChain相似的链模型来解决这个问题

代码稍后附上
0 请登录后投票
   发表时间:2008-08-01  
准备直接利用org.aopalliance.intercept的MethodInterceptor
但是看不到源代码不知道里面具体是怎么实现有序列表的
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics