服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

spring阶段性的一点感受

一直不能坐下来好好学习一下, 最近研究了spring framework, 一点感受:

1. ioc

传统方法:如果动态设置一个对象属性,可以借助javareflection机制完成,invoke()激活返回调用

class cls = class.forname("com.eking.user");

method mtd = cls.getmethod("setname",new class[]{string.class});

object obj = (object)cls.newinstance();

mtd.invoke(obj,new object[]{"erica"});

return obj;

        在spring中, 面向接口编程,动态代理机制:beanwrapper, beanfactory,applicationcontext提供了管理javabean的包装器,所有的一切都在容器中配置,dependency injection.

也可以不提供接口,cglib与dynamic proxy的代理机制基本类似,只是其动态生成的代理对象并非某接口的实现,而是针对目标类扩展的子类。换句话说,dynamic proxy返回的动态代理类,是目标类所实现的接口的另一个实版本,它实现了对目标类的代理(如同userdaoproxy与userdaoimp的关系)。而cglib返回的动态代理类,则是目标代理类的一个子类(代理类扩展了userdaoimp类)。

2. aop

   各种通知类型有methodinterceptor (来自aop联盟的拦截器api)和定义在org.springframework.aop包中的 通知接口。所有通知必须实现org.aopalliance.aop.advice标签接口。 取出就可使用的通知有 methodinterceptorthrowsadvicebeforeadviceafterreturningadvice

    也可以自己写个拦截器,在实现自己的方法之前出发某个动作,执行一些处理。

3. webapplicationcontext

1)  web.xml 中通过声明监听器接口 servlet类加载
通过: 
   <listener>
      <listener-class>org.springframework.web.context.contextloaderlistener</listener-class>
   </listener-->
或:
   <servlet>
      <servlet-name>springcontextservlet</servlet-name>
      <servlet-class>org.springframework.web.context.contextloaderservlet</servlet-class>
      <load-on-startup>1</load-on-startup>
   </servlet>
web
容器会自动加载 /web-inf/applicationcontext.xml 初始化 applicationcontex t实例;
也可以通过
   <context-param>
      <param-name>contextconfiglocation</param-name>
      <param-value>/web-inf/applicationcontext-*.xml</param-value>
   </context-param>
使 web 容器加载指定名称路径的 spring 配置文件。

我个人认为listerner要比servlet更好一些,因为listerner监听应用的启动和结束,而servlet得启动要稍微延迟一些,如果在这时要做一些业务的操作,启动的前后顺序是有影响的。

那么在contextloaderlistenercontextloaderservlet中到底做了什么呢?
contextloaderlistener为例,我们可以看到
public void contextinitialized(servletcontextevent event) {
this.contextloader = createcontextloader();
this.contextloader.initwebapplicationcontext(event.getservletcontext());
}
protected contextloader createcontextloader() {
return new contextloader();
}
        contextloader
是一个工具类,用来初始化webapplicationcontext,其主要方法就是initwebapplicationcontext,我们继续追踪initwebapplicationcontext这个方法(具体代码我不贴出,大家可以看spring中的源码),我们发现,原来contextloader是把webapplicationcontextxmlwebapplicationcontext是默认实现类)放在了servletcontext中,servletcontext也是一个“容器”,也是一个类似map的结构,而webapplicationcontextservletcontext中的key就是webapplicationcontext.root_web_application_context_attribute我们如果要使用webapplicationcontext则需要从servletcontext取出,spring提供了一webapplicationcontextutils类,可以方便的取出webapplicationcontext,只要把servletcontext传入就可以了。

2) struts-config.xml 中通过插件加载
通过
    <plug-in classname="org.springframework.web.struts.contextloaderplugin">
        <set-property property="contextconfiglocation"
            value="/web-inf/applicationcontext.xml,
                   /web-inf/action-servlet.xml"/>
    </plug-in>
来加载 spring 配置文件。

struts-config.xmlaction的配置变成类似下面的样子
<action attribute="aform" name="aform" path="/aaction" scope="request" type="org.springframework.web.struts.delegatingactionproxy">
<forward name="forward" path="forward.jsp" />
</action>

别急,我们还是来看一下contextloaderplugin的源码(源码不再贴出),我们可以发现,原来contextloaderplugin仍然是把webapplicationcontext放在servletcontext中,只是这个key不太一样了,这个key值为contextloaderplugin.servlet_context_prefix+moduleconfig.getprefix()(具体请查看源代码),这下好了,我们知道了webapplicationcontext放在哪里,只要我们在web应用中能够取到servletcontext也就能取到webapplicationcontext

4.struts+spring+hibernate

spring live中myusers,一个3层架构的web 程序,通过一个action 来调用业务代理,再通过它来回调 dao类。下面的流程图表示了myusers是如何工作的。数字表明了流程的先后顺序,从web层(useraction)到中间层(usermanager),再到数据层(userdao),然后返回。

spring是aop, usermanager和userdao都是接口.

1)    web层(useraction) :调用中间层的接口方法,将usermanager作为属性注入

2)     中间层(usermanager):将userdao作为属性注入,其实现主要是调用数据层接口的一些方法; 它处于事务控制中

3)     数据层(userdao):实现类继承hibernatedaosupport类,在该类中可以调用gethibernatetemplate()的一些方法执行具体的数据操作。

spring配置部分文件:

 

<bean id="userdao" class="com.eking.entity.userdaoimp">

            <property name="sessionfactory">

                <ref local="sessionfactory" />

            </property>

        </bean>

      

       <bean id="usermanagertarget" class="com.eking.service.usermanagerimp">

             <property name="userdao"><ref local="userdao"/></property>

       </bean>

   

       <bean id="usermanager" class="org.springframework.transaction.interceptor.transactionproxyfactorybean">

            <property name="transactionmanager">

                 <ref local="transactionmanager" />

            </property>

            <property name="target">

                 <ref local="usermanagertarget" />

            </property>

            <property name="transactionattributes">

                 <props>

                      <prop key="insert*">propagation_required</prop>

                      <prop key="get*">propagation_required</prop>

                      <prop key="is*">propagation_required</prop>

                  </props>

            </property>

       </bean>

      

       <bean name="/login" class="com.eking.struts.action.loginaction" singleton="false">

            <property name="usermanager">

                 <ref local="usermanager" />

           </property>

      </bean>


spring live中myusers,一个3层架构的web 程序,通过一个action 来调用业务代理,再通过它来回调 dao类。下面的流程图表示了myusers是如何工作的。数字表明了流程的先后顺序,从web层(useraction)到中间层(usermanager),再到数据层(userdao),然后返回。

spring是aop, usermanager和userdao都是接口.

1)    web层(useraction) :调用中间层的接口方法,将usermanager作为属性注入

2)     中间层(usermanager):将userdao作为属性注入,其实现主要是调用数据层接口的一些方法; 它处于事务控制中

3)     数据层(userdao):实现类继承hibernatedaosupport类,在该类中可以调用gethibernatetemplate()的一些方法执行具体的数据操作。

spring配置部分文件:

 

<bean id="userdao" class="com.eking.entity.userdaoimp">

            <property name="sessionfactory">

                <ref local="sessionfactory" />

            </property>

        </bean>