Simon:你现在用spring用的多么?
Simon:目前 blog 中频繁出现两个名词:spring、groovy
Echou:热门啊
Simon:最近还在研究么?
Echou:嗯,我现在一直都在用spring
Simon:感觉怎样?
Echou:很好用。也很方便
Simon:评价这么高啊
Echou:确实是这样的。
Simon:那看来我不用不行了
Echou:建议一定要用。
Simon:怎么开始?
Echou:你是要在webapp中用吗?
Simon:是啊
Echou:web层你打算用什么呢?
Echou:spring自己有一个mvc
Simon:还是用echo吧
Simon:它自己的v层?
Echou:是的。
Simon:我还是喜欢echo的rich client
Simon:你的blogsite也没用它的v吧?
Echou:我不知道spring和echo怎么结合。
Echou:对,blogsite用tapestry
Simon:那它和tapestry结合如何呢?
Echou:spring将所有的bean放在一个application context对象中
Simon:哦?
Echou:只要echo能够获得这个对象就能结合在一起了。
Simon:那应该没问题的吧
Echou:嗯。我想也应该没啥问题。
Echou:只是不是那么无缝而已。
Simon:呵呵,无所谓啦
Simon:它的核心优点在哪儿?
Echou:我用得最多的是用它管理beans和它的hibernate支持
Simon:哦?
Echou:我给你看一下blogsite的applicationContext配置
Simon:好~
Simon:这个是干吗的?PropertyPlaceholderConfigurer
Echou:配置文件里面可能有很多值要引用别的属性值
Echou:比如,你看下面一个proxool的配置,有很多${...}
Simon:对啊
Echou:它能够将这些${..}替换成真正的值。
Simon:用这个文件中的 file {blogsite.webapp.root}/WEB-INF/config/mckoi.properties 来替换?
Echou:是的。
Echou:它自己维护一个properties,
Simon:明白
Echou:将其他的${..}替换成properties里面对应的一个值
Simon:这个比较有意思
Echou:在properties里找不到的话,就到system properties里找。
Simon:嗯
Echou:一个<property>对应一个setter
Echou:它可以根据property的类型,自己用PropertyEditor自动转换。
Simon:哦?
Simon:什么叫 一个<property>对应一个setter ?
Echou:PropertyPlaceholderConfigurer有一个配置是<property name="properties"><value>alias=blogsite</value></property>
Simon:对阿
Echou:这个类的定义是:\\ private Properties properties;\\ public void setProperties(Properties p) {..}\\ public Properties getProperties(); {..}
Echou:它可以从alias=blogsite自动创建一个Properties对象,再调用setProperties()
Simon:哦?不是自动的set?
Echou:总要自己定义吧。
Simon:呵呵,明白
Echou:属性值也可以是其他bean的引用。
Echou:这样就形成一个依赖关系,引用的bean会在它之前创建。
Simon:会不会出现类型不匹配的情况?
Echou:不会的。
Echou:它用JavaBeans的PropertyEditor来设置属性。
Echou:对于Properties类型,它有一个PropertiesEditor类。
Echou:类型就不必担心。
Simon:呵呵
Simon:比如它本来要接受一个int类型的
Echou:它的IoC有好几种方式解决bean之间的依赖问题。
Simon:但是我给了一个字符串类型?
Echou:只要这个字符串能转换为int就行。
Simon:那如果不行呢?
Echou:那就抛出异常。
Simon:呵呵,这个东西只能运行期抛出异常了
Echou:是的。
Simon:嗯,这就是配置编程所面临的一个问题了
Echou:是的。不过它的配置属于静态配置。如果运行期抛出异常,改改配置就行了。
Echou:直到没有错误为止。
Simon:嗯,就是担心有时候会改错,然后没测试到
Echou:配置还好一点,脚本编程就更容易错了。
Simon:对啊
Simon:这就是两个对立的东西
Echou:嘿嘿,话题扯远了。
Simon:跑题定理嘛
Echou:spring可以从属性设置获得bean的依赖关系
Echou:也可以从构造函数获得依赖关系。
Echou:还不行的话,可以手工添加依赖关系。
Simon:依赖关系怎么添加?
Echou:<bean id="sessionFactory" class="blogsite.util.MySessionFactoryBean?" depends-on="proxool" autowire="byName">
Echou:depends-on就是手工添加依赖关系
Simon:哦
Simon:那这表示什么呢?先创建一个 proxool 对象?
Simon:这个proxool对象用在哪儿呢?
Echou:对,表示proxool在sessionFactory之前创建
Echou:在这里proxool对象是用来初始化Proxool系统,增加一个blogsite的alias。hibernate会用到这个alias
Simon:哦,就是说不是显性的调用了
Echou:hibernate和proxool的依赖关系没办法由spring自动获得,只好加一个depends-on了。
Simon:嗯,明白
Echou:spring可以接受任何class来创建bean
Echou:没有规定一个类必须实现它的某些接口。
Echou:这样就十分灵活。
Simon:?
Simon:不定义接口的话
Simon:它怎么能够让对方接受这个对象呢?
Echou:就是说,任何一个类都可以放到<bean id=".." class="..">里。
Simon:哦,呵呵
Echou:它的任务是按照适当的顺序创建并维护这些beans。
Simon:只是创建bean的时候不需要接口
Echou:当然,如果一个类实现了它的一些方法,能够提供附加的功能。
Simon:什么方法?
Echou:比如InitializingBean接口,这个bean会在属性设置完毕之后得到通知,调用afterPropertiesSet()
Simon:哦,了解
Echou:还有FactoryBean接口,表示这个bean是一个factory,引用这个bean时得到的不是bean自身,而是它生成的一个对象。
Simon:这个比较强悍
Echou:blogsite.util.MySessionFactoryBean就是一个FactoryBean?
Simon:上次我试用pico的时候,就这点没搞清楚
Echou:我的这个类是从Spring的LocalSessionFactoryBean派生的。
Simon:我不知道它什么时候产生一个Factory,什么时候是这个Factory产生的对象
Simon:后来也没空去研究
Echou:是hibernate SessionFactory的工厂bean?.
Echou:spring还有一个autowire
Simon:哦?
Echou:还是刚才那个例子:\\ <bean id="sessionFactory" class="blogsite.util.MyessionFactoryBean" depends-on="proxool" autowire="byName">
Echou:错了,这个好像用不着autowire
Simon:呵呵,autowire用中文怎么说?
Echou:<bean id="hibernateInterceptor" class="org.springframework.orm.hibernate.HibernateInterceptor?" autowire="byName"/>
Echou:不知道怎么翻译
Simon:那是一个什么样的动作?
Echou:看这个hibernateInterceptor
Echou:它有一个属性是sessionFactory (getter/setter)
Simon:嗯
Echou:autowire="byName" spring会在application context中查找有没有名字叫做sessionFactory的bean
Simon:明白了
Echou:有的话就设置给它。
Echou:还有byType
Simon:好像picocontainer里面缺省就是这样,把人搞得很晕。不过它好像是byType
Echou:但是spring不建议用autowire功能,因为大一点的系统里autowire很容易把人弄晕。
Simon:没错
Echou:刚才说的是spring的配置。
Echou:现在说说它的orm支持。
Echou:用hibernate的时候,比较麻烦的就是session获取、释放,以及异常的处理。
Echou:spring将我们从这些工作中解放出来。
Echou:我在blogsite里面是用它的aop来实现这个功能。
Simon:嗯,我还没来得及看那个源码呢
Echou:HibernateInterceptor就是用来准备和释放session。
Echou:它的xml schema十分简单。
Echou:就是 bean, property, value或者list,map,properties,ref
Simon:好像是
Echou:在spring中配置hibernate,一般是这样的:
# 配置一个LocalSessionFacotryBean
# 配置一个HibernateInterceptor,引用这个session factory bean
# 业务逻辑是用DAO模式来实现。对于DAO,要定义一个接口和一个实现类
# 创建一个Proxy,它实现这个DAO接口,作用于DAO的实现类实例,并应用hibernateInterceptor
Simon:那这样岂不是对所有用Hibernate的项目都一样?
Echou:是一样的。
Simon:上次我和同事谈起这种用法
Echou:如果有必要的话,还可以增加事务管理。
Simon:他说存在一个问题是,需要访问数据库的类就那么几个
Simon:如果用你这种方法做的话,岂不是鼓励大家都去访问数据库?
Echou:但是hibernate有cache,它不一定会去访问数据库。
Echou:必须要访问的时候就得访问。
Simon:嗯...
Simon:这样会有性能的问题吗?每次都去取session
Echou:它好像采用了ThreadLocal的方法。
Simon:哦?
Echou:是的。所以不是每次都去openSession
Simon:明白,所以实际上不会花很长的时间
Echou:对。
Echou:它还将HibernateException, SQLException等数据库有关异常全部统一。
Simon:哦?怎么讲?
Echou:\\ catch (HibernateException ex) {\\ throw convertHibernateAccessException(ex);\\ }\\ catch (SQLException ex) {\\ throw convertJdbcAccessException(ex);\\ }\\ catch (RuntimeException ex) {\\ // callback code threw application exception\\ throw ex;\\ }
Simon:它转换为什么异常?
Echou:dao的业务逻辑代码中也不需要管异常处理。
Echou:DataAccessException extends NestedRuntimeException?
Simon:那异常谁去处理?
Echou:一般通过HibernateTemplate来访问hibernate
Simon:这个HibernateTemplate是什么概念?
Simon:是不是 commond 的概念?
Echou:差不多。
Simon:嗯,那异常呢?
Simon:最终肯定要有人来处理的。
Echou:HibernateTemplate的核心是execute(HibernateCallback? callback)方法
Echou:HibernateCallback.doInHibernate(Session session) throws HibernateException?, SQLException
Simon:这个做法和 prevayler 很像
Echou:HibernateCallback一般是用匿名类来实现。
Simon:它的所有增删改动作都是command
Echou:hibernatetemplate也提供了一些辅助方法,简化代码,比如find, get, load, save,等。
Simon:哦
Echou:这种匿名类的方法好还是不好,见仁见智了。
Simon:对啊
Simon:有时候会把人搞晕掉
Echou:可惜hibernatetemplate没有辅助方法来简化Query。
Echou:用到Query的话还是只能包到一个匿名类里。
Simon:是么?
Echou:是啊。
Echou:spring我基本上就只用到这些。
Simon:也不错啦,我看最近blog上有很多关于它的讨论
Simon:还有人用在swing当中
Echou:是啊,它不一定是用在webapp中。
Simon:嗯...
Simon:从目前而言,它给你带来些什么好处呢?
Simon:第一、简化配置
Simon:第二、hibernate 的使用方便些
Simon:还有呢?
Echou:它可以解决singleton的问题。
Simon:怎么讲?
Echou:就不用自己维护singleton了。
Echou:一般实现singleton都是在代码中实现,构造函数写成protected或者private,再定义一个static实例。
Simon:没错
Echou:只有这样才能保证singleton。
Simon:对啊,spring里面呢?
Echou:用spring的话,就不必这样了。你可以配置成只有一个实例,也可以配置成多个实例。
Echou:配置成只有一个实例,它就成了singleton
Simon:哦?
Simon:那怎么取这个实例呢?
Echou:applicationContext可以获得这个实例。
Echou:getBean(beanName)
Simon:这样就可以自由的决定是否使用 singleton了
Echou:是的。
Simon:是不是还可以用它实现pool?
Echou:你的意思是在配置文件中配置多个实例吗?
Simon:可以控制有多少个bean么?
Echou:哦,对了,最新的rc2版本还集成了Quartz和Timer
Simon:嗯,我看到了
Echou:好像不能控制~~~
Simon:什么叫不能控制
Echou:没有什么配置可以指定多少个实例。
Echou:应该也可以实现。
Simon:哦,那就算了,呵呵
Simon:我只是瞎说的
Echou:spring里bean可以是singleton也可以不是singleton
Simon:嗯
Echou:singleton表示的是,一个<bean>定义总是只得到一个实例。
Simon:没错
Echou:要实现池的话,你可以设置singleton为false
Simon:自己加一些控制
Echou:然后自己控制这个池的大小。
Simon:嗯,有意思,不过我还是没觉得它特别有用
Echou:我觉得这两点已经很有用了。
Echou:很方便了。
javac 有个属性叫 compiler,必须把它设置为 "extJavac" 才能找到 javac,而且在1.6中,还多了一个 ant-launch 的包,觉得比起以前来还麻烦些。如果觉得不爽,还是退回到 1.5.4 好了
http://blogsite.3322.org:8080/jspwiki/Wiki.jsp?page=OneMinuteWiki