论坛首页 Java企业应用论坛

Spring源代码分析的PDF版本发布

浏览 17109 次
精华帖 (18) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-10-29  
方便大家阅读,请多留言,多指正!
   发表时间:2008-10-29  
楼主什么时候对hibernate源码做研究呀? 期待着....
0 请登录后投票
   发表时间:2008-11-20   最后修改:2008-11-21
发布了一个用javaeye生成电子书做的PDF。地址是:
[url]http://jiwenke.iteye.com/blog/pdf [/url]
0 请登录后投票
   发表时间:2008-12-02  
jiwenke 写道
方便大家阅读,请多留言,多指正!


jiwenke楼主大侠,请帮我分析一下下面的问题吧。
我想以我目前这点功力,确实难以搞明白这个事,请帮帮忙吧。

请点击下面的链接:
http://www.iteye.com/topic/285113
0 请登录后投票
   发表时间:2008-12-02  
你太谦虚了
请问你用的spring是多少版本的。我以前看的版本比较低,想整个checkout出来看看你这个问题 - 不一定能搞定啊
另外,如果你要改spring代码,可以把版本checkout出来后,自己build一个。看看改动是不是有效。
0 请登录后投票
   发表时间:2008-12-02  
感谢LZ的及时回复!

为了研究这个问题,我刚换了最新的spring:spring-framework-2.5.6-with-dependencies.zip
之前用的是2.5.5好象,因为用eclipse进行debug时,对不上源代码,所以干脆把环境中的spring.jar全换作了2.5.6。
另:cglib-2.2.jar

我倒是没有整个checkout,build。只是下了最新的包和源码。
就是改,肯定也是在开发环境中建立spring的包,然后把想改的类拷进行改。
我这水平也不想全部搞明白,只想就所我自己碰到的具体问题搞清楚。弄不清楚这事,我老是很不爽。
0 请登录后投票
   发表时间:2008-12-03   最后修改:2008-12-03
我看了一下代码,在Spring2.5.6,似乎如果要支持带参数的构造函数生成proxy,要手动的去调用setConstructorArguments();可以参考测试用例:
	public void testWithNoArgConstructor() {
		NoArgCtorTestBean target = new NoArgCtorTestBean("b", 1);
		target.reset();

		mockTargetSource.setTarget(target);
		AdvisedSupport pc = new AdvisedSupport(new Class[]{});
		pc.setTargetSource(mockTargetSource);
		Cglib2AopProxy aop = new Cglib2AopProxy(pc);
	        aop.setConstructorArguments(new Object[] {"Rob Harrop", new Integer(22)},
				new Class[] {String.class, int.class});
		NoArgCtorTestBean proxy = (NoArgCtorTestBean) aop.getProxy();
		proxy = (NoArgCtorTestBean) aop.getProxy();

		assertNotNull("Proxy should be null", proxy);
	}

如果是不带参数的构造函数的proxy,spring提供的用例是这样的:
	public void testProxyAProxy() {
		ITestBean target = new TestBean();

		mockTargetSource.setTarget(target);
		AdvisedSupport as = new AdvisedSupport(new Class[]{});
		as.setTargetSource(mockTargetSource);
		as.addAdvice(new NopInterceptor());
		Cglib2AopProxy cglib = new Cglib2AopProxy(as);

		ITestBean proxy1 = (ITestBean) cglib.getProxy();

		mockTargetSource.setTarget(proxy1);
		as = new AdvisedSupport(new Class[]{});
		as.setTargetSource(mockTargetSource);
		as.addAdvice(new NopInterceptor());
		cglib = new Cglib2AopProxy(as);

		ITestBean proxy2 = (ITestBean) cglib.getProxy();
	}

不知道我的理解对不对?或者不需要重新build spring,只是要手动的调用一下。从代码上看,Spring的实现方式默认是为不带参数的构造函数生成Proxy,也许是Spring觉得这种使用方式不好,因而支持不够?可能大多数使用方式是不带参数的构造函数,如果要注入的话通过set函数来完成吧。
0 请登录后投票
   发表时间:2008-12-03   最后修改:2008-12-03
jiwenke 写道
我看了一下代码,在Spring2.5.6,似乎如果要支持带参数的构造函数生成proxy,要手动的去调用setConstructorArguments();可以参考测试用例:
	public void testWithNoArgConstructor() {
		NoArgCtorTestBean target = new NoArgCtorTestBean("b", 1);
		target.reset();

		mockTargetSource.setTarget(target);
		AdvisedSupport pc = new AdvisedSupport(new Class[]{});
		pc.setTargetSource(mockTargetSource);
		Cglib2AopProxy aop = new Cglib2AopProxy(pc);
	        aop.setConstructorArguments(new Object[] {"Rob Harrop", new Integer(22)},
				new Class[] {String.class, int.class});
		NoArgCtorTestBean proxy = (NoArgCtorTestBean) aop.getProxy();
		proxy = (NoArgCtorTestBean) aop.getProxy();

		assertNotNull("Proxy should be null", proxy);
	}

如果是不带参数的构造函数的proxy,spring提供的用例是这样的:
	public void testProxyAProxy() {
		ITestBean target = new TestBean();

		mockTargetSource.setTarget(target);
		AdvisedSupport as = new AdvisedSupport(new Class[]{});
		as.setTargetSource(mockTargetSource);
		as.addAdvice(new NopInterceptor());
		Cglib2AopProxy cglib = new Cglib2AopProxy(as);

		ITestBean proxy1 = (ITestBean) cglib.getProxy();

		mockTargetSource.setTarget(proxy1);
		as = new AdvisedSupport(new Class[]{});
		as.setTargetSource(mockTargetSource);
		as.addAdvice(new NopInterceptor());
		cglib = new Cglib2AopProxy(as);

		ITestBean proxy2 = (ITestBean) cglib.getProxy();
	}

不知道我的理解对不对?或者不需要重新build spring,只是要手动的调用一下。从代码上看,Spring的实现方式默认是为不带参数的构造函数生成Proxy,也许是Spring觉得这种使用方式不好,因而支持不够?可能大多数使用方式是不带参数的构造函数,如果要注入的话通过set函数来完成吧。

感谢回答,感谢您帮忙做的调查。

这个结论跟我之前Debug的结论是一致的,也就是对于没有实现接口的类,又没有默认构造函数时,目前的Spring是无法实现AOP拦截的!

不过,我已经找到了解决方案,并且也基本上清楚了CGLIB的AOP的是如何实现的。
稍后,我打算写一篇总结性的文章阐述一下。
写完了,在这:
http://www.iteye.com/topic/286215
0 请登录后投票
   发表时间:2008-12-04   最后修改:2008-12-04
发了邮件问了一下, 下面是Spring Source oleg zhurakousky的回复:
No it does not:
    The proxies are created by dynamically sub-classing the actual class, which requires class to expose default constructor. If you don't you'll get IllegalArgumentException "Superclass has no null constructors but no arguments were given.", which means if you have a Spring bean that defines constructor injection it will not work and I think this is the problem you are having.

我的邮件原文是:
Hi,
In the usage of the AOP , we found that with the proxy class usign CGLIB with contructor arg - a exception throw with "org.springframework.aop.framework.AopConfigException". Checking the source code and the testcases(Version 2.5.6) and found that Spring actually doesn't support it. Is that means Spring not encourage this use cases or it is a missing functionality? - it sounds tricky, can any one help to clarify it ? Thanks your time so much!

Tracing code in the Cglib2AopProxy line197:
            if (this.constructorArgs != null) {
                proxy = enhancer.create(this.constructorArgTypes, this.constructorArgs);
            }
            else {
                proxy = enhancer.create();
            }

it is the exception occurred.
And by trace the use of the Cglib2AopProxy.setConstructorArguments - It is only called in the testcases instead of production code. Does it means when use don't permit to AOP those class with arg constructor directly?

public void testWithNoArgConstructor() { 

NoArgCtorTestBean target = new NoArgCtorTestBean("b", 1);  
target.reset();  
   
mockTargetSource.setTarget(target);  
AdvisedSupport pc = new AdvisedSupport(new Class[]{});  
pc.setTargetSource(mockTargetSource);  
Cglib2AopProxy aop = new Cglib2AopProxy(pc);  
aop.setConstructorArguments(new Object[] {"Rob Harrop", new Integer(22)}, new Class[] {String.class, int.class});  
NoArgCtorTestBean proxy = (NoArgCtorTestBean) aop.getProxy();  
proxy = (NoArgCtorTestBean) aop.getProxy();  
assertNotNull("Proxy should be null", proxy);  
}  

Oleg的意思是说if you have a Spring bean that defines constructor injection it will not work and I think this is the problem you are having - 不允许使用构造器注入来建立Spring bean AOP.但我觉得奇怪,不知道这是cglib的限制还是spring自己功能上的限制 - 看到了楼上的解决方案啊,为什么spring不提供?
0 请登录后投票
   发表时间:2008-12-04  
感谢楼主不遗余力的调查这个问题。
虽然我不知道Oleg是谁,但是似乎老外也有这样的结论。

考虑应该是Spring自己功能上的限制吧。
Debug源码后,感觉目前Spring框架本身想解决这个限制,难度还是比较大。
0 请登录后投票
论坛首页 Java企业应用版

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