WEB开发网
开发学院WEB开发Jsp spring阶段性的一点感受 阅读

spring阶段性的一点感受

 2008-01-05 18:35:14 来源:WEB开发网   
核心提示:一直不能坐下来好好学习一下, 最近研究了sPRing framework,spring阶段性的一点感受, 一点感受:1. IOC传统方法:假如动态设置一个对象属性,可以借助java的Reflection机制完成,invoke()激活返回调用Class cls = Class.forName("com.ekin

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

1. IOC

传统方法:假如动态设置一个对象属性,可以借助java的Reflection机制完成,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得启动要稍微延迟一些,假如在这时要做一些业务的操作,启动的前后顺序是有影响的。

那么在ContextLoaderListener和ContextLoaderServlet中到底做了什么呢?
以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是把WebApplicationContext(XmlWebApplicationContext是默认实现类)放在了ServletContext中,ServletContext也是一个“容器”,也是一个类似Map的结构,而WebApplicationContext在ServletContext中的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.xml中Action的配置变成类似下面的样子
<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>

   

    <bean id="userManagerTarget" class="com.eking.service.UserManagerImp">

 


Tags:spring 阶段性 一点

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接