Spring初始了解笔记

来源:互联网 发布:养生域名交易 编辑:程序博客网 时间:2024/05/10 06:24

1、spring依赖库
 * SPRING_HOME/dist/spring.jar
 * SPRING_HOME/lib/jakarta-commons/commons-logging.jar
 * SPRING_HOME/lib/log4j/log4j-1.2.14.jar
 
2、拷贝spring配置文件到src下

3、拷贝log4j配置文件到src下

4、在UserManagerImpl中提供构造函数或setter方法,spring将实例化好的UserDao实现注入给我们
在Spring的配置文件applicationContext.xml中
<bean id="userDao4MySqlImpl" class="com.bjsxt.spring.dao.UserDao4MySqlImpl"/>
<bean id="userDao4OracleImpl" class="com.bjsxt.spring.dao.UserDao4OracleImpl"/>
 
<bean id="userManager" class="com.bjsxt.spring.manager.UserManagerImpl">
  
 <!-- 构造方法注入
 <constructor-arg ref="userDao4OracleImpl"/>
  -->
   <property name="userDao" ref="userDao4OracleImpl"/>
</bean>
解释:com.bjsxt.spring.manager.UserManagerImpl中有属性UserDao 且有set方法
而userDao4MySqlImpl、userDao4OracleImpl都实现了UserDao接口.在客户端进行测试时,用到
BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
  
  UserManager userManager = (UserManager)factory.getBean("userManager");//这里的userManager就是配置文件中某个的

id名字,其实就像List list=new ArrayList();实现接口,
  userManager.save("张三", "123");


5、让spring管理我们的对象创建和依赖,必须在spring配置中进行定义

6、编写客户端

 BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
  
  UserManager userManager = (UserManager)factory.getBean("userManager");
 
  userManager.save("张三", "123");
  System.out.println("asfgdg");

spring Ioc容器的关键点:
 * 必须将被管理的对象定义到spring配置文件中
 * 必须定义构造函数或setter方法,让spring将对象注入过来
 

 

////////////////////////////////////////
1、spring的普通属性注入 
 参见:spring文档3.3章节
在测试Spring的几种数据类型注入时,可以定义全局BeanFactory 然后重写setup方法,这样每次调用BeanFactory时,就不用赋值了。
而applicationContext-*.xml指的是applicationContext-为开始的xml文件,因为Spring默认配置文件时applicationContext.xml但是上述一

个文件不能满足大量数据需要配置的需求。所以相应的文件数量就会增加。一般就会根据功能进行定义名字。像applicationContext-

beans.xml,
applicationContext-editor.xml以及applicationContext-other.xml看一下名字就知道什么意思,后缀名是beans的就是实体Bean的配置了。

这样为后期的维护也起到很好的帮助。
private BeanFactory factory;
 
 @Override
 protected void setUp() throws Exception {
  factory = new ClassPathXmlApplicationContext("applicationContext-*.xml"); 
 }

 
什么是属性编辑器,作用?
 * 自定义属性编辑器,spring配置文件中的字符串转换成相应的对象进行注入
 spring已经有内置的属性编辑器,我们可以根据需求自己定义属性编辑器

 
 * 如何定义属性编辑器?
  * 继承PropertyEditorSupport类,覆写setAsText()方法,参见:UtilDatePropertyEditor.java
////////////////////////////////////////
public class UtilDatePropertyEditor extends PropertyEditorSupport {

 private String format="yyyy-MM-dd";
 
 @Override
 public void setAsText(String text) throws IllegalArgumentException {
  System.out.println("UtilDatePropertyEditor.saveAsText() -- text=" + text);
  
  SimpleDateFormat sdf = new SimpleDateFormat(format);
  try {
   Date d = sdf.parse(text);
   this.setValue(d);
  } catch (ParseException e) {
   e.printStackTrace();
  }
 }

 public void setFormat(String format) {
  this.format = format;
 }

}
////////////////////////////////////////
  * 将属性编辑器注册到spring中,参见:applicationContext-editor.xml

////////////////////////////////////////
 <!-- 定义属性编辑器 -->     
 <bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
  <property name="customEditors">
   <map>
    <entry key="java.util.Date">
     <bean class="com.bjsxt.spring.UtilDatePropertyEditor">
      <property name="format" value="yyyy-MM-dd"/>
     </bean>
    </entry>
   </map>
  </property>
 </bean> 
其中bean id="customEditorConfigurer"以及其下层的<property name="customEditors">都是一定的,没有变化。要将属性编辑器注册,只要

在<property name="customEditors">下加入类似的配置文件:  <map>
    <entry >
     <bean class="">
      <property name="" ></property>
     </bean>
    </entry>
   </map>
其实这和struts中的转换器差不多。这里不再详解。
////////////////////////////////////////
 
几种Class的关系:
public class Bean2 {

 private Bean3 bean3;
 
 private Bean4 bean4;
 
 private Bean5 bean5;
/////////////////////////////////////// 
依赖对象的注入方式,可以采用:
 * ref属性
 * <ref>标签
 * 内部<bean>来定义
////////////////////////////////////////
配置文件:
<bean id="bean2" class="com.bjsxt.spring.Bean2">
  <property name="bean3" ref="bean3"/>
  <property name="bean4">
   <ref bean="bean4"/>
  </property> 
  <property name="bean5" ref="bean5"/>
 </bean>
///////////////////////////////////////
内部<Bean>的定义:
<bean id="bean3" class="com.bjsxt.spring.Bean3">
  <property name="id" value="1000"/>
  <property name="name">
   <value>Jack</value>
  </property>
  <property name="password" value="123"/>
 </bean>
 
 <bean id="bean4" class="com.bjsxt.spring.Bean4">
  <property name="id" value="1000"/>
  <property name="name" value="Jack"/>
 </bean>
 
 
 <bean id="bean5" class="com.bjsxt.spring.Bean5">
  <property name="age" value="20"/>
 </bean>
////////////////////////////////////////
 
如何将公共的注入定义描述出来?
 * 通过<bean>标签定义公共的属性,指定abstract=true
////////////////////////////////////////
<bean id="beanAbstract" abstract="true">
     <property name="id" value="1000"/>
     <property name="name" value="Jack"/>
   </bean>        
   /////////////////////////////////////
 * 具有相同属性的类在<bean>标签中指定其parent属性
Bean3和Bean4有公共相同的属性:int id;
String name;那么上面定义的父类标签abstract="true"同时初始了id 和name的值,这样只要Bean3和Bean4继承beanAbstract既可以。其实就

是继承吧。(现在的感觉就是)
下面是:
   <bean id="bean3" class="com.bjsxt.spring.Bean3" parent="beanAbstract">
     <property name="name" value="Tom"/>//也许有人会问,为什么要加此句,因为bean3还有一个属性,父类中没有,所以要

写。(对于初学者,这只是一种不需要解释的解释。)
     <property name="password" value="123"/>
   </bean>       
  
   <bean id="bean4" class="com.bjsxt.spring.Bean4" parent="beanAbstract"/>
///////////////////////////////////////
输出结果:
bean2.bean3.id=1000
bean2.bean3.name=Tom
bean2.bean3.password=123
bean2.bean4.id=1000
bean2.bean4.name=Jack
bean2.bean5.age=20
////////////////////////////////////////

 下面介绍一下:abstract="true"的含义:abstract="true"
一个bean组件没有指定实现类,而是通过设置abstract="true"属性来组织spring 容器实例化组件

设置一个bean的属性abstract="true",表明这个bean只能作为其他bean的父bean使用,不能直接被实例化。

//////////////////////////////////////// 
 

下面介绍一下Spring Bean的作用域:
spring Bean的作用域:
 
scope可以取值: 
 * singleton:每次调用getBean的时候返回相同的实例,这时默认情况。
 * prototype:每次调用getBean的时候返回不同的实例
/////////////////////////////////////// 
  配置文件:
<!--
 <bean id="bean1" class="com.bjsxt.spring.Bean1" scope="singleton"/>
  -->
 <bean id="bean1" class="com.bjsxt.spring.Bean1" scope="prototype"/>
////////////////////////////////////////
 测试:
Bean1 bean11 = (Bean1)factory.getBean("bean1");
  Bean1 bean12 = (Bean1)factory.getBean("bean1");
  if (bean11 == bean12) {
   System.out.println("bean11==bean12");
  }else {
   System.out.println("bean11!=bean12");
  }
配置文件不同,则结果就会不同。
////////////////////////////////////////

下面介绍一下:自动装配问题:
1、根据名称自动装配;

首先:在<beans xmlns=""
 最后面加上+
 default-autowire="byName"即可

>

然后:配置<bean>时,不需要臃余的配置:将原来的<!--
 <bean id="bean2" class="com.bjsxt.spring.Bean2">
  <property name="bean3" ref="bean3"/>
  <property name="bean4">
   <ref bean="bean4"/>
  </property> 
  <property name="bean5" ref="bean5"/>
 </bean>
  -->
改为:<bean id="bean2" class="com.bjsxt.spring.Bean2"/>
即可。
但是有一点必须记住其中的id的值就是
在类Bean2中:public class Bean2 {

 private Bean3 bean3;
 
 private Bean4 bean4;
 
 private Bean5 bean5;
如果根据bean2调用bean3,bean4,bean4,那么配置文件怎么写呢?
首先,则依次定义三个bean 其中id的值必须为Bean2中的set,get后面的字符串,其实就是对应的bean3,bean4,bean5如果不这样定义,那么

根据bean2得到另外三个,就会出错。因为Bean2 bean2 = (Bean2)factory.getBean("bean2");
bean2.getBean3().getId()
在类Bean2中找不到相应的关联对象。
但是,其中的Bean2的<bean>id配置可以随意,因为Bean2是通过标签得到,而其他是通过类之间的关系得到。
2、根据类型自动装配;
只要将上述的default-autowire="byName"改为default-autowire="byType"即可,
那么像bean3、bean4、bean5可以为任意值,即不用与类Bean2中的名字一直,所以id的值可以为任意的。因为它会根据类型进行寻找。
我感觉default-autowire="byType"一般加在为引导bean定义的文件的页面中的。即在配置Bean2标签 <bean id="bean2"

class="com.bjsxt.spring.Bean2"/>在同一个页面,否则就会出错。即有谁引导,就定义在谁那里。(有点方言色彩。不好意思!)。
////////////////////////////////////////
下面介绍一下:动态代理:
要继承:java.lang.reflect.InvocationHandler;
public class SecurityHandler implements InvocationHandler {

 private Object targetObject;
 
 public Object newPoxy(Object targetObject){
   this.targetObject=targetObject;
   return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
          targetObject.getClass().getInterfaces(),

this);
 }
//下面的方法是该类继承InvocationHandler时,自动生成的,然后自己在重写。
 public Object invoke(Object proxy, Method method, Object[] args)
   throws Throwable {

  checkSecurity();
  
  Object ret=null;
  
  try {
   
   ret=method.invoke(this.targetObject, args);//这句话的意思可能就是返回对象时,就会自动加载
   
  } catch (RuntimeException e) {
   
   e.printStackTrace();
   throw new java.lang.RuntimeException(e);
  }
  return ret;
 }
////////////////////////////////////////

客户端测试:
public static void main(String[] args) {

  SecurityHandler handler=new SecurityHandler();
  
  UserManager usermanager=(UserManager)handler.newPoxy(new UserManagerImpl()); // UserManagerImpl是UserManager

接口的实现。
  
  usermanager.addUser("w", "ewer");//调用该方法时,会自动调用checkSecurity()方法,
 }

////////////////////////////////////////
输出结果:----------checkSecurity()---------------
-------UserManagerImpl.addUser()----------

///////////////////////////////////////
spring对AOP的只是(采用Annotation的方式)

1、spring依赖库
 * SPRING_HOME/dist/spring.jar
 * SPRING_HOME/lib/jakarta-commons/commons-logging.jar
 * SPRING_HOME/lib/log4j/log4j-1.2.14.jar
 * SPRING_HOME/lib/aspectj/*.jar
 
2、采用Aspect定义切面

2、在Aspect定义Pointcut和Advice

4、启用AspectJ对Annotation的支持并且将Aspect类和目标对象配置到Ioc容器中

注意:在这种方法定义中,切入点的方法是不被执行的,它存在的目的仅仅是为了重用切入点
即Advice中通过方法名引用这个切人点

AOP:
 * Cross cutting concern
 * Aspect
 * Advice
 * Pointcut
 * Joinpoint
 * Weave
 * Target Object
 * Proxy
 * Introduction

////////////////////////////////////////
文件配置:首先在ApplicationContext.xml文件中加入:
<aop:aspectj-autoproxy/>
 <bean id="securityHandler" class="com.bjsxt.spring.SecurityHandler"/>          
 <bean id="userManager" class="com.bjsxt.spring.UserManagerImpl"/>
其中的<bean>定义是,在用到AOP的类,其中UserManager.java只是个接口,不用配了。
//////////////////////////////////////
其中SecurityHandler.java
的主要代码:
@Aspect

public class SecurityHandler {
 
 /**
  * 定义Pointcut,Pointcut的名称就是allAddMethod,此方法不能有返回值和参数,该方法只是一个
  * 标识
  *
  * Pointcut的内容是一个表达式,描述那些对象的那些方法(订阅Joinpoint)
  */
 @Pointcut("execution(* add*(..)) || execution(* del*(..))")
 private void allAddMethod(){};
 
 /**
  * 定义Advice,标识在那个切入点何处织入此方法
  */
 
 @After("allAddMethod()")//在方法后加上checkSecurity()执行
//@Before("allAddMethod()")
 private void checkSecurity() {
  System.out.println("----------checkSecurity()---------------");
 }
 
}这里的意思是,在调用某某对象的add**()和del**()方法时,会自动调用checkSecurity()方法。
///////////////////////////////////////
////////////////////////////////////////

下面介绍:静态配置文件方式实现AOP:
spring对AOP的只是(采用配置文件的方式)

1、spring依赖库
 * SPRING_HOME/dist/spring.jar
 * SPRING_HOME/lib/jakarta-commons/commons-logging.jar
 * SPRING_HOME/lib/log4j/log4j-1.2.14.jar
 * SPRING_HOME/lib/aspectj/*.jar
2、配置如下
<bean id="securityHandler" class="com.bjsxt.spring.SecurityHandler"/>          
 
 <bean id="userManager" class="com.bjsxt.spring.UserManagerImpl"/>
 <aop:config>
  <aop:aspect id="security" ref="securityHandler">
   <aop:pointcut id="allAddMethod" expression="execution(* com.bjsxt.spring.UserManagerImpl.add*(..))"/>
/*只是实现以add开始的方法。
要是实现类中的所用的方法,则采用
<aop:pointcut id="allAddMethod" expression="execution(* com.bjsxt.spring.UserManagerImpl.*(..))"/>
同时不用加上这句:<aop:aspectj-autoproxy/>
*/
   <aop:before method="checkSecurity" pointcut-ref="allAddMethod"/>
  </aop:aspect>
 </aop:config> 
  
////////////////////////////////////////
其中:public class SecurityHandler {
 
 private void checkSecurity() {
  System.out.println("----------checkSecurity()---------------");
 }
////////////////////////////////////////

spring对AOP的支持

Aspect默认情况下不用实现接口,但对于目标对象(UserManagerImpl.java),在默认情况下必须实现接口
如果没有实现接口必须引入CGLIB库
//客户端代码:
 public static void main(String[] args) {
  BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
  
  UserManager userManager = (UserManager)factory.getBean("userManager");
  
  userManager.addUser("张三", "123");
  //userManager.deleteUser(1);
 }
/////////////////////////////////////////
我们可以通过Advice中添加一个JoinPoint参数,这个值会由spring自动传入,从JoinPoint中可以取得
参数值、方法名等等

public class SecurityHandler {
 
 private void checkSecurity(JoinPoint joinPoint) {
  Object[] args = joinPoint.getArgs();
  for (int i=0; i<args.length; i++) {
   System.out.println(args[i]);
  }
  
  System.out.println(joinPoint.getSignature().getName());
  System.out.println("----------checkSecurity()---------------");
 }
 
}
////////////////////////////////////////
其中applicationContext.xml
 <bean id="securityHandler" class="com.bjsxt.spring.SecurityHandler"/>          
 
 <bean id="userManager" class="com.bjsxt.spring.UserManagerImpl"/>
 
 <aop:config>
  <aop:aspect id="security" ref="securityHandler">
   <aop:pointcut id="allAddMethod" expression="execution(* com.bjsxt.spring.UserManagerImpl.add*(..))"/>
   <aop:before method="checkSecurity" pointcut-ref="allAddMethod"/>
  </aop:aspect>
 </aop:config> 
////////////////////////////////////////
////////////////////////////////////////spring对AOP的支持

1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP
3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换


如何强制使用CGLIB实现AOP?
 * 添加CGLIB库,SPRING_HOME/cglib/*.jar
 * 在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>
 
JDK动态代理和CGLIB字节码生成的区别?
 * JDK动态代理只能对实现了接口的类生成代理,而不能针对类
 * CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法
   因为是继承,所以该类或方法最好不要声明成final 
  
////////////////////////////////////////

 

采用编程式事务

1、getCurrentSession()与openSession()的区别?
 * 采用getCurrentSession()创建的session会绑定到当前线程中,而采用openSession()
   创建的session则不会

 * 采用getCurrentSession()创建的session在commit或rollback时会自动关闭,而采用openSession()
   创建的session必须手动关闭
  
2、使用getCurrentSession()需要在hibernate.cfg.xml文件中加入如下配置:
 * 如果使用的是本地事务(jdbc事务)
 <property name="hibernate.current_session_context_class">thread</property>
 * 如果使用的是全局事务(jta事务)
 <property name="hibernate.current_session_context_class">jta</property>    
////////////////////////////////////////三种事务差异
1、JDBC事务控制的局限性在一个数据库连接内,但是其使用简单。
2、JTA事务的功能强大,事务可以跨越多个数据库或多个DAO,使用也比较复杂。
3、容器事务,主要指的是J2EE应用服务器提供的事务管理,局限于EJB应用使用。
五、总结
事务控制是构建J2EE应用不可缺少的一部分,合理选择应用何种事务对整个应用系统来说至关重要。一般说来,在单个JDBC 连接连接的情况下

可以选择JDBC事务,在跨多个连接或者数据库情况下,需要选择使用JTA事务,如果用到了EJB,则可以考虑使用EJB容器事务。
////////////////////////////////////////

/////////////////////////////////////////
采用声明式事务
/////////////////////////////////////////////////
采用声明式事务:说明:为了便于管理,事务配置在applicationContext-common.xml中,
类的配置即<bean>配置在applicationContext-beans.xml中。
////////////////////////////////////////////////

1、声明式事务配置
 * 配置SessionFactory
////////////////////////////////////////
 <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  <property name="configLocation">
   <value>classpath:hibernate.cfg.xml</value>
  </property> 
 </bean>  
////////////////////////////////////////  
 * 配置事务管理器
////////////////////////////////////////
<!-- 配置事务管理器 -->
 <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
  <property name="sessionFactory">
   <ref bean="sessionFactory"/>
  </property> 
 </bean>
////////////////////////////////////////
 * 事务的传播特性
////////////////////////////////////////
<!-- 配置事务的传播特性 -->
 <tx:advice id="txAdvice" transaction-manager="transactionManager">
  <tx:attributes>
   <tx:method name="add*" propagation="REQUIRED"/>
   <tx:method name="del*" propagation="REQUIRED"/>
   <tx:method name="modify*" propagation="REQUIRED"/>
   <tx:method name="*" read-only="true"/>//这行的意思是其他方法是只读的形式,这样有利于性能的优化。而前

面增、减、改是可以请求事务的。
  </tx:attributes>
 </tx:advice>
////////////////////////////////////////

 * 那些类那些方法使用事务

////////////////////////////////////////
 <!-- 那些类的哪些方法参与事务 -->
 <aop:config>
  
  <aop:pointcut id="allManagerMethod" expression="execution(* com.bjsxt.usermgr.manager.*.*(..))"/>
  <aop:advisor pointcut-ref="allManagerMethod" advice-ref="txAdvice"/>//这里的<aop:advisor>类似于Aspect
 </aop:config>
////////////////////////////////////////
aop:advisor 和 aop:aspect的区别

advisor 策略 是通过切入点 找到符合条件的方法 再根据策略 进行相应方法的事务控制


而aop:aspect   是根据切入点找到符合条件的方法 然后再根据切面的类型(After、Before、Around)来适时的执行引入bean的方法
<aop:config>
  <aop:aspect id="security" ref="securityHandler">
   <aop:pointcut id="allAddMethod" expression="execution(* com.bjsxt.spring.UserManagerImpl.*(..))"/>
   <aop:before method="checkSecurity" pointcut-ref="allAddMethod"/>
  </aop:aspect>
 </aop:config> 
////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
"advisors"这个概念来自Spring1.2对AOP的支持,在AspectJ中是没有等价的概念。 advisor就像一个小的自包含的切面,这个切面只有一个通

知。 切面自身通过一个bean表示,并且必须实现一个通知接口, 在 第 7.3.2 节 “Spring里的通知类型” 中我们会讨论相应的接口。

Advisors可以很好的利用AspectJ切入点表达式。

Spring 2.0 通过 <aop:advisor> 元素来支持advisor 概念。 你将会发现它大多数情况下会和transactional advice一起使用,

transactional advice在Spring 2.0中有自己的命名空间。


////////////////////////////////////////

2、编写业务逻辑方法
   针对这个小实验,实现的功能是在添加用户信息时,实现系统日志的记录,即用户表,日志表,涉及到两个表。
这对这些业务,设计了两个接口,一个是日志管理,一个是用户管理。
下面简单介绍一下日志管理接口实现:
////////////////////////////////////////public class LogManagerImpl extends HibernateDaoSupport implements LogManager {

 public void addLog(Log log) {
  this.getHibernateTemplate().save(log);
 }
}
如果在Spring中用到Hibernate即在类中用到Hibernate,就必须继承HibernateDaoSupport
因为在类的方法中用到了getHibernateTemplate()方法。
////////////////////////////////////////
 * 继承HibernateDaoSupport类,使用HibernateTemplate来持久化,HibernateTemplate是
   Hibernate Session的轻量级封装
 * 默认情况下运行期异常才会回滚(包括继承了RuntimeException子类),普通异常是不会滚的
 * 编写业务逻辑方法时,最好将异常一直向上抛出,在表示层(struts)处理
 * 关于事务边界的设置,通常设置到业务层,不要添加到Dao上 

3、了解事务的几种传播特性
 1. PROPAGATION_REQUIRED: 如果存在一个事务,则支持当前事务。如果没有事务则开启
 2. PROPAGATION_SUPPORTS: 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行
 3. PROPAGATION_MANDATORY: 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。
 4. PROPAGATION_REQUIRES_NEW: 总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。
 5. PROPAGATION_NOT_SUPPORTED: 总是非事务地执行,并挂起任何存在的事务。
 6. PROPAGATION_NEVER: 总是非事务地执行,如果存在一个活动事务,则抛出异常
 7. PROPAGATION_NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务,
      则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行

4、Spring事务的隔离级别
 1. ISOLATION_DEFAULT: 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.
      另外四个与JDBC的隔离级别相对应
 2. ISOLATION_READ_UNCOMMITTED: 这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据。
      这种隔离级别会产生脏读,不可重复读和幻像读。
 3. ISOLATION_READ_COMMITTED: 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提

交的数据
 4. ISOLATION_REPEATABLE_READ: 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。
      它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。
 5. ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。
      除了防止脏读,不可重复读外,还避免了幻像读。     
////////////////////////////////////////////////////////////////////////////////

spring+struts的集成(第一种集成方案)
原理:在Action中取得BeanFactory对象,然后通过BeanFactory获取业务逻辑对象

1、spring和struts依赖库配置
 * 配置struts
  --拷贝struts类库和jstl类库
  --修改web.xml文件来配置ActionServlet
  --提供struts-config.xml文件
  --提供国际化资源文件
 * 配置spring
  --拷贝spring类库
  --提供spring配置文件
  
2、在struts的Action中调用如下代码取得BeanFactory
 BeanFactory factory = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getSession

().getServletContext());
为什么要这样写呢?
因为像factory的生成,如果每次执行以下action 都会实例化一次,BeanFactory factory = new ClassPathXmlApplicationContext

("applicationContext-beans.xml");
这样有必要吗?同时,会占用好多资源。
所以,我们会用到上述方法,在servlet初始化时,执行一次,以后就不用再实例化了。
但是我们必须在web.xml文件中配置一下信息。
//////////////////////////////////////// <context-param>
   <param-name>contextConfigLocation</param-name>
   <param-value>classpath*:applicationContext-*.xml,/WEB-INF/applicationContext-*.xml</param-value>
  </context-param>
//////////////////////////////////////
/WEB-INF/applicationContext-*.xml指的是,具体的路径。而classpath*:applicationContext-*.xml指的是src根目录下的文件。
但是最终的<param-name>contextConfigLocation</param-name>中的值contextConfigLocation为唯一的。因为在类的方法属性中要一致。
////////////////////////////////////////

<listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>
这是注册用的,就是是上述的配置有效。

  ////////////////////////////////////////

3、通过BeanFactory取得业务对象,调用业务逻辑方法   
ApplicationContext pc = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getSession().getServletContext

());

UserManager userManager = (UserManager)pc.getBean("userManager");

为什么这样可以?因为ApplicationContext 继承了BeanFactory。其实都是一样的。就像ArrayList继承List一样的意思。
////////////////////////////////////////  
     
////////////////////////////////////////

 

spring+struts的集成(第二种集成方案)
原理:将业务逻辑对象通过spring注入到Action中,从而避免了在Action类中的直接代码查询

1、spring和struts依赖库配置
 * 配置struts
  --拷贝struts类库和jstl类库
  --修改web.xml文件来配置ActionServlet
  --提供struts-config.xml文件
  --提供国际化资源文件
 * 配置spring
  --拷贝spring类库
  --提供spring配置文件

////////////////////////////////////////
2、因为Action需要调用业务逻辑方法,所以需要在Action中提供setter方法,让spring将业务逻辑对象注入过来
private UserManager userManager;
 public void setUserManager(UserManager userManager) {
  this.userManager = userManager;
 }
////////////////////////////////////////


3、在struts-config.xml文件中配置Action

  * <action>标签中的type属性需要修改为org.springframework.web.struts.DelegatingActionProxy
   DelegatingActionProxy是一个Action,主要作用是取得BeanFactory,然后根据<action>中的path属性值
   到IoC容器中取得本次请求对应的Action
///////////////////////////////////////////////////////////////////////////////////////////////////////////
<action path="/login"
    type="org.springframework.web.struts.DelegatingActionProxy"
    name="loginForm"
    scope="request" 
  >
   <forward name="success" path="/success.jsp"/>
  </action>
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
  
4、在spring配置文件中需要定义struts的Action,如:
//////////////////////////////////////////////////////////////////////////////////////////////////
 <bean name="/login" class="com.bjsxt.usermgr.actions.LoginAction" scope="prototype">
  <property name="userManager" ref="userManager"/>//因为在Action定义了private UserManager userManager;就是业务 

                                                               //逻辑对象
 </bean>
//////////////////////////////////////////////////////////////////////////////////////////////
 * 必须使用name属性,name属性值必须和struts-config.xml文件中<action>标签的path属性值一致
 * 必须注入业务逻辑对象
 * 建议将scope设置为prototype,这样就避免了struts Action的线程安全问题,因为这样设置,每次调用返回不同的实例,
而将scope设置为singleton,每次调用只生成一个实例。
//////////////////////////////////////////////////////////////////////////////////////////////////      
  此时的一个感觉就是,要想把相应的类注入Ioc容器中的同时,将关联类的对象也注入,可以在该类的中定义像private

UserManager userManager;然后再设置set方法即可,一般注入用到的都是set方法吧。(此时的感觉认识。)
但是在Spring的配置文件中,还要定义相应的对象bean标签,然后包容的类中在引用id即可。
就是:
 <bean id="userManager" class="com.bjsxt.usermgr.manager.UserManagerImpl"/>
        <bean name="/login" class="com.bjsxt.usermgr.actions.LoginAction" scope="prototype">
  <property name="userManager" ref="userManager"/>
 </bean>
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
在一些类中定义的方法是static类型的,那么像引用this.getHibernateTemplate()就会出错。因为this代表的是实例化。
示例:
下面:
private static SessionFactory sessionFactory;
public static List getItemCategoryList() {
  List itemCategoryList = null;
  try {
   HibernateTemplate ht = new HibernateTemplate(sessionFactory);
   return ht.find("from ItemCategory a order by a.id");
  }catch(Exception e) {
   //记录日志,log4j等......
   e.printStackTrace();
  }
  return itemCategoryList;
 }


public void setSessionFactory(SessionFactory sessionFactory) {
  Functions.sessionFactory = sessionFactory;
 }
说明:在方法getItemCategoryList中因为是static类型的,不能用this.getHibernateTemplate()获得HibernateTemplate 对象,又因为

HibernateTemplate 实例是通过sessionFactory获得的,所以只要在类中再定义即可,因为在static中引用,所以还要定义为static类型的,

同时要注入spring,还要定义set方法。
///////////////////////////////////////////
还有像Spring中对象的注入,如果设置的set方法是static那么也不会注入成功。在Spring配置文件中标签<listener></listener>的作用,就

是读取与spring的配置有关的文件的,像hinbernate.cfg.xml像struts-config.xml等等。

////////////////////////////////////////

原创粉丝点击