spring 2.5 基础知识和与其他框架的集成

spring环境搭建:

  一:导入spring2.5所需的包,在classpath目录下建一个名为"beans.xml"模板文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
      
      这里写代码 </beans>

       二:spring得到实例:一:通过该类本身的构造方法(可以进行构造注入)得到实例,然后再进行setter注入。

                      二是:通过其他类的静态方法或其他bean的动态方法(可以进行构造注入)得到未知实例,未知实例再调用setter进行注入

   例如:

    <bean id="id号"  class="包名.类名"/>

   <bean id="id号"  class="包名.类名" factory-method="该类的静态方法"/>

   <bean id="id号"  factory-bean="其他的bean" factory-method="其他bean中动态方法" />

   解释:如果在"bean" 标签上加了 scope="prototype"设置,表示原型,那么spring容器开启时,不能获得实例,只有getBean()时才会得到实例,这样得到的实例不是同一个实例。加了lazy-init="true"表示懒加载,那么spring容器开启时,不能获得实例,但得到是同一个实例。同理,如果在"beans" 标签上加了 default-lazy-init="true",则是对所有bean设置的。

    如果在"bean" 标签上加了 init-method="该bean对应类中的方法"设置,则表示得到实例后就调用的方法。

    如果在"bean" 标签上加了 destroy-method="该bean对应类中的方法"设置,则表示实例销毁前调用的方法(spring 容器关闭,则实例销毁)

    A:依赖注入:

    一种方式为构造注入:<constructor-arg index="0"  type="包名.类名" value="***"/>         //基本类型和String类型可以不用写type

     一种方式为setter方法注入:

        <property name=" setter方法名的关键字"   value=""/>          //适用于基本类型和String类型

        <property name="setter方法名的关键字" [ref=""|local=""]/>         //其中local表示本地的bean,就是该xml文件中bean,

        <property name="setter方法名的关键字"><bean class="包名.类名"/></property>

       如果bean中的属性是集合类型,那么一般采用setter方式进行注入:

          对于Set集合:

<property name="sets">
              <set>
                  <value>李鹏生</value>
                  <value>李小龙</value>
                  <value>李嘉城</value>
                  <value>李鹏</value>
              </set>
          </property>

          对于List集合和数组:

<property name="list">
                  <list>
                      <value>秦始皇</value>
                      <value>李世民</value>
                      <value>李自成</value>
                  </list>
          </property>

          对于Map集合:

<property name="map">
              <map>
                  <entry key="key1" value="one"/>
                  <entry key="key2" value="two"/>
                  <entry key="key3" value="three"/>
              </map>
          </property>

          对于Properties集合:

 <property name="prop">
              <props>
                  <prop key="key1">第一个</prop>
                  <prop key="key2">第二个</prop>
                  <prop key="key3">第三个</prop>
              </props>
          </property>
 <property name="hibernateProperties">
            <value>
                hibernate.dialect=org.hibernate.dialect.MySQLDialect
                hibernate.hbm2ddl.auto=update
                hibernate.show_sql=false
            </value>
         </property>

B:采用注解方式进行依赖注入:

  在beans.xml中加入代码:

 xmlns:context=http://www.springframework.org/schema/context
 
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd

 

           打开注解配置项:

    <context:annotation-config/> 

  两种注解:一是:@Autowired    是按类型装配     二是:@Resource  默认是按名称装配,就是根据id名称装配,如果找不到,会按类型装配。

    下面举两个例子说明下:  如:@Resource PersonDao  personDao; 其中PersonDao是一个接口,如果PersonDaoImpl是PersonDao接口的实现类。它是怎么装配的呢,首先它是找到名称为"personDao"id的bean,如果找到,但并不是PersonDao接口的实现类,则出异常;如果找不到名称为"personDao"id的bean,则按类型找,找PersonDao接口的实现类,如果实现类是多个,那么就会异常。

所以说接口的实现类为多个的话,就按名称装配。同样的道理,如果一个类有它的子类,而我们想得到子类的实例,然后进行向上转型,那么就要按照名称装配,而不是类型装配了。

  例子:@Resource private Ni  n,或者这样:private Ni n; @Resource  public void setNi(Ni n){this.n=n;}  方法名可以是任意名称,不一定是"setNi",本质是调用这个方法而已,只是容易见名思义。

    建议:使用@Resource 注解;变量名称为bean的id名称;使用"setNi"这种格式的方法名。本质是调用这个方法而已,只是容易见名思义。

 三:spring容器的实例化:

    例如:

    ApplicationContext  ctx=new ClassPathXmlApplicationContext(new String[]{"beans.xml"});  --可以实例化多个.xml文件。

    得到bean的实例,得到之后要进行相应的转型,如:类名,父类,接口。

    (类名,父类,接口)  引用名=(类名,父类,接口) ctx.getBean("该bean相应的id名"); 

                          四:spring 容器自动扫描和管理bean(代替了在beans.xml配置的<bean id="" class=""/>):

  在beans.xml中加入代码:<context:component-scan base-package="com.itcast">(可以删掉之前的<context:annotation-config/> ) --其 中"com.itcast"也包括该包下的子包下类。

  然后在该包及该包的子包下的类加上@Service(服务层组件)或@Controller(控制层组件)或@Repository(DAO层组件)或@Component(泛指组件)表示该类由

spring容器实例。

  那么我们又是怎样得到哪些bean的实例呢,默认是这样得到的:该类的首字母小写。如:类名为:PersonServiceImpl,那么它的id为:personServiceImpl。

当然我们也可以更改bean的id.如:@Service("所要更改的id名称")。

  我们也可以设置bean的作用域:没设置,默认是单例,也就是@Scope("singleton"),@Scope("[singleton|prototype|request|session|global session]")。

  如果在类的某方法前面加上@PostConstruct 注解,表示该bean类实例后将执行该方法,通常命名为"init";如果在类的某方法前面加上@PreDestroy 注解,表示该bean类实例后将执行该方法,通常命名为"destroy".

  总结:一种.xml中有bean标签,一种.xml中没有bean标签(即自动扫描和注解)。一种是.xml中依赖注入,一种是注解方式的依赖注入。

  建议:使用@Resource 注解;变量名称为bean的id名称;使用"setNi"这种格式的方法名。本质是调用这个方法而已,只是容易见名思义。

  spring管理的bean是怎么完成该bean父类的依赖注入的。如果父类是采用的是注解注入,则它按照装配原则自动完成的。

  如果父类是采用的是在.xml中依赖注入,则需要在管理的bean中的bean标签中加入parent="父类bean所对应的id名称"。

            五:spring集成jdbc和spring集成hibernate

      步骤:一:配置数据源  二:配置SessionFactory(如果是集成hibernate的就会配置)  三:配置事务管理器  四:配置事务。

    其中一、二步骤用于数据库连接方面的,三、四步骤用于Service层方面的,利用AOP技术对DAO层中的方法进行事务管理

    配置数据源:

    代码列子:

    这里用到了.properties文件,当然你也可以不用,不过这样修改起来方便。

  例子:

    classpath下的jdbc.properties文件的代码:

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/itcast?useUnicode=true&characterEncoding=UTF-8
username=root
password=admin
initialSize=1
maxActive=500
maxIdle=2
minIdle=1

    相应beans.xml下的代码:

 <context:property-placeholder location="classpath:jdbc.properties"/>
     <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${driverClassName}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
         <!-- 连接池启动时的初始值 -->
         <property name="initialSize" value="${initialSize}"/>
         <!-- 连接池的最大值 -->
         <property name="maxActive" value="${maxActive}"/>
         <!-- 最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 -->
         <property name="maxIdle" value="${maxIdle}"/>
         <!--  最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请 -->
         <property name="minIdle" value="${minIdle}"/>
     </bean>

    <context:property-placeholder location="classpath:jdbc.properties"/>        指明.properties文件。

  配置SessionFactory(将数据源注入到SessionFactory中):

    例子一:

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
         <property name="dataSource" ref="dataSource"/>
         <property name="mappingResources">
            <list>
              <value>cn/itcast/bean/Person.hbm.xml</value>
             </list>
         </property>
         <property name="hibernateProperties">
            <value>
                hibernate.dialect=org.hibernate.dialect.MySQLDialect
                hibernate.hbm2ddl.auto=update
                hibernate.show_sql=false
            </value>
         </property>
    </bean>

  例子二(数据源和SessionFactory都用到了.properties 文件):

      classpath下jdbc.properties文件代码:

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/cms?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&autoReconnect=true
jdbc.username=root
jdbc.password=123456
jdbc.maxActive=300
jdbc.maxWait=5000
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.show_sql=true
hibernate.hbm2ddl.auto=update
hibernate.format_sql=true
hibernate.connection.autocommit=false
hibernate.order_updates=true
hibernate.jdbc.use_scrollable_resultset=true
hibernate.use_sql_comments=true
hibernate.connection.release_mode=after_transaction
hibernate.current_session_context_class=thread

    相应的beans.xml代码(这里就省略不写数据源了,当然也要指明.properties文件,这里也省略了):

<bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="dataSource">
        </property>
          <!-- 映射所有实体 -->
        <property name="packagesToScan">
            <list>
                <value>com.yojosources.admin.po</value>
                <value>com.yojosources.business.po</value>
                <value>com.yojosources.member.po</value>
                <value>com.yojosources.privilege.po</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="javax.persistence.validation.mode">none</prop>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
   <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>

                <!-- 输出所有SQL语句到控制台 -->
                <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>

                <!-- 在log和console中打印出更漂亮的SQL -->
                <prop key="hibernate.format_sql">${hibernate.format_sql}</prop>


                <!-- 允许被缓存的JDBC 连接开启自动提交 -->
                <prop key="hibernate.connection.autocommit">${hibernate.connection.autocommit}</prop>

                <!-- 强制Hibernate按照被更新数据的主键,为SQL更新排序。 -->
                <prop key="hibernate.order_updates">${hibernate.order_updates}</prop>

                <!-- 允许Hibernate使用JDBC2的可滚动结果集。 -->
                <prop key="hibernate.jdbc.use_scrollable_resultset">${hibernate.jdbc.use_scrollable_resultset}</prop>


                <!-- hibernate将在SQL中生成有助于调式的注解信息 -->
                <prop key="hibernate.use_sql_comments">${hibernate.use_sql_comments}</prop>

                <!-- 指定Hibernate在何时释放 JDBC 连接 -->
                <prop key="hibernate.connection.release_mode">${hibernate.connection.release_mode}</prop>

                <!-- 同一个事务用一个session -->
<!--                <prop key="hibernate.current_session_context_class">${hibernate.current_session_context_class}</prop>-->

            </props>
        </property>

    </bean>

   解释:这里用到了packagesToScan属性,它是指定要扫描哪些包里的数据库映射类,是mappingResource属性对立的又一种方式。先说说packagesToSan的用法:

1.  <property name="packagesToScan" value="com.xxx.entity" />, 会解析成"classpath*:com/xxx/entity**/*.class",这个路径可以找出com/xxx/entity根目录下的类文件 

2. <property name="packagesToScan" value="com.xxx.entity.*" />, 会解析成"classpath*:com/xxx/entity/***/*.class",这个路径可以找出com/xxx/entity根目录下一级子目录中的类文件,如com/xxx/entity/son/Hi.class ,而不能找出com/xxx/entity目录下的类文件。

3.  <property name="packagesToScan" value="com.xxx.entity." />(注意最后的点) , 会转换成"classpath*:com/xxx/entity/**/*.class",这个路径可以找出com/xxx/entity根目录下及其子孙目录下所有的类文件. 一般来讲,这些就是我们要的文件。

 数据库映射类(它没有配置文件hbm.xml,全部采用注解的方式),例子:
package com.yojosources.admin.po;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.springframework.stereotype.Repository;

/**
 * 文章实体
 * @author Beamstar
 */
@Entity
@Repository(value="t_article")
@Table(name="t_article")
public class Article {
    
    /**
     * 主键
     * 文章 id
     */
    private Integer ar_id;
    
    /**
     * 文章 标题
     */
    private String ar_name;
    /**
     * 文章发布人
     */
    private String ar_author;
    /**
     * 文章内容
     */
    private String ar_content;
    /**
     * 发布日期
     */
    private Date ar_date;
    
    /**
     * 浏览次数
     */
    private Integer ar_readCount;
    
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name = "article_id", unique = true, nullable = false)
    public Integer getAr_id() {
        return ar_id;
    }
    public void setAr_id(Integer arId) {
        ar_id = arId;
    }
    
    
    @Column(name="headline")
    public String getAr_name() {
        return ar_name;
    }
    public void setAr_name(String arName) {
        ar_name = arName;
    }
    @Column(name="author")
    public String getAr_author() {
        return ar_author;
    }
    public void setAr_author(String arAuthor) {
        ar_author = arAuthor;
    }
    
    @Lob
    @Column(name="article_contents", columnDefinition="TEXT", nullable=true)
    public String getAr_content() {
        return ar_content;
    }
    public void setAr_content(String arContent) {
        ar_content = arContent;
    }
    
    @Column(name="artcleues_date")
    @Temporal(TemporalType.TIMESTAMP)
    public Date getAr_date() {
        return ar_date;
    }
    public void setAr_date(Date arDate) {
        ar_date = arDate;
    }
    
    
    @Column(name="page_view")
    public Integer getAr_readCount() {
        return ar_readCount;
    }
    
    public void setAr_readCount(Integer arReadCount) {
        ar_readCount = arReadCount;
    }
    public Article() {
        super();
        // TODO Auto-generated constructor stub
    }
    public Article(Integer arId, String arName, String arAuthor,
            String arContent, Date arDate, Integer arReadCount) {
        super();
        ar_id = arId;
        ar_name = arName;
        ar_author = arAuthor;
        ar_content = arContent;
        ar_date = arDate;
        ar_readCount = arReadCount;
    }
    
    
    

}

     配置事务管理器:

    jdbc:

 <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
         <property name="dataSource" ref="dataSource"/>  
 </bean> 

     hibernate:

<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
          <property name="sessionFactory" ref="sessionFactory"/>
</bean>

     配置事务(利用了AOP技术。主要是拦截方法(建议不管是注解方式还是.xml方式,最好是拦截类中的方法,而不是接口);配置事务(主要指事务的传播性);调用方法时,那么它生成的是代理对象):

   首先要引入命名空间,在beans.xml中插入代码:

 xmlns:aop="http://www.springframework.org/schema/aop" 

 http://www.springframework.org/schema/aop //引入AOP命名空间
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd



xmlns:tx="http://www.springframework.org/schema/tx"

http://www.springframework.org/schema/tx                   //引入事务命名空间
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd

   在.xml里配置事务:

    例子一:

 <aop:config proxy-target-class="true">              //proxy-target-class="true"表示允许实现了接口的类,生成的代理对象可以是类的对象。
          <aop:pointcut id="transactionPointcut" expression="execution(* cn.itcast.service.PersonService.*(..))"/>
          <aop:advisor advice-ref="txAdvice" pointcut-ref="transactionPointcut" />
 </aop:config> 
 <tx:advice id="txAdvice" transaction-manager="txManager">
          <tx:attributes>
            <tx:method name="save" propagation="REQUIRED"/>
          </tx:attributes> 
 </tx:advice>

       例子二:

    <aop:config proxy-target-class="true">
        <aop:pointcut expression="execution(public * com.yojosources.service.impl.*.*(..))"
            id="bussinessService" />
        <aop:pointcut expression="execution(public * com.yojosources..*Service.*(..))"
            id="service" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="bussinessService" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="service" />
    </aop:config>

    <tx:advice id="txAdvice" transaction-manager="transactionManager">               
        <tx:attributes>
            <tx:method name="save*" propagation="REQUIRED" />                       
            <tx:method name="add*" propagation="REQUIRED" />
            <tx:method name="create*" propagation="REQUIRED" />
            <tx:method name="insert*" propagation="REQUIRED" />
            <tx:method name="update*" propagation="REQUIRED" />
            <tx:method name="merge*" propagation="REQUIRED" />
            <tx:method name="del*" propagation="REQUIRED" />
            <tx:method name="remove*" propagation="REQUIRED" />
            <tx:method name="put*" propagation="REQUIRED" />
            <tx:method name="get*" propagation="SUPPORTS" read-only="true" />         //read-only="true"表示该方法只执行读取数据操作
            <tx:method name="count*" propagation="SUPPORTS" read-only="true" />
            <tx:method name="find*" propagation="SUPPORTS" read-only="true" />
            <tx:method name="query*" propagation="SUPPORTS" read-only="true" />
            <tx:method name="list*" propagation="SUPPORTS" read-only="true" />
            <tx:method name="*" propagation="SUPPORTS" read-only="true" />              "*" 表示其他的方法
            <tx:method name="batchSaveOrUpdate" propagation="REQUIRES_NEW" />
        </tx:attributes>
    </tx:advice>

      注解方式配置事务:

     在beans.xml加上代码:<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true" />

     例子:

package cn.itcast.service.impl;

import java.util.List;

import javax.annotation.Resource;

import org.hibernate.SessionFactory;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import cn.itcast.bean.Person;
import cn.itcast.service.PersonService;

@Transactional
public class PersonServiceBean implements PersonService {
    @Resource private SessionFactory sessionFactory;
    
    @Transactional(readOnly=true)
    public void save(Person person){
        sessionFactory.getCurrentSession().persist(person);
    }
    
    public void update(Person person){
        sessionFactory.getCurrentSession().merge(person);
    }
    @Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
    public Person getPerson(Integer personid){
        return (Person)sessionFactory.getCurrentSession().get(Person.class, personid);
    }

    public void delete(Integer personid){
        sessionFactory.getCurrentSession().delete(
                sessionFactory.getCurrentSession().load(Person.class, personid));
    }
    @Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
    @SuppressWarnings("unchecked")
    public List<Person> getPersons(){        
        return sessionFactory.getCurrentSession().createQuery("from Person").list();
    }
    
}

     事务的传播性:

常用的传播性主要是 REQUIRED,NOT_SUPPORTED,SUPPORTS。

                       spring集成struts

  spring容器实例化交给web.xml:

 

    <!-- 指定spring的配置文件,默认从web根目录寻找配置文件,我们可以通过spring提供的classpath:前缀指定从类路径下寻找 -->
    <context-param>
       <param-name>contextConfigLocation</param-name>
       <param-value>classpath:beans.xml</param-value>           //多个.xml文件用逗号隔开
    </context-param>
    <!-- 对Spring容器进行实例化 -->
    <listener>
          <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    web容器实例化spring容器,详细见:http://blog.csdn.net/yangxueyong/article/details/6579700

  当然spring也提供了方法让我们得到spring容器的实例,从而得到想要的bean。

           集成struts1.x(其实就是让struts1.x中的action交给spring管理)

    代码例子:

  beans.xml中的代码:

  struts-config.xml中的代码:

            集成struts2.x(其实就是让struts2.x中的action交给spring管理)

  beans.xml中的代码:

  struts.xml中代码:

<constant name="struts.objectFactory" value="spring" />     //将action交给spring管理。

     注意其中的class="".

这里采用了在.xml中,当然也可以采用注解方式.

struts.xml默认放在classpath路径的根目录下。web容器会找到,如果要改变路径,那么要在web.xml中配置,详细见:http://blog.163.com/wunan_23/blog/static/1955623202011102105925798/

 

posted on 2019-09-03 17:41  芝麻开花——节节高  阅读(267)  评论(0编辑  收藏  举报

导航