1.建立第一个sprint项目(java project)
步骤:window-->preferences-->java-->user libraries-->new-->给要加的包命名-->add jars-->
1)、spring的依赖包
*spring_home/dist/spring.jar
*spring_home/lib/jakarta-commons/commons-logging.jar
*soring_home/lob/log4j/jog4j-1.2.14.jar
2).拷贝spring配置文件到src下
3).拷贝log4j配置文件到src下
4).在UserManagerImpl中提供构造函数(或set方法),spring将实例化好的UserDao实现诸如给我们
5.让spring关联我们的对象创建和依赖,必须在sprin配置文件(applcationContext.xml)中进行定义,如果在配置文件中打印的时候没有提示,可以加上相应文件的配置提示,eg加入AOP的提示文件加入方法如下:
*******
window-->preferrnces-->MyEclipse-->Files and Editors-->XML Catalog-->User Specified Entries-->add-->Key Type(选择URI),Location(File System加入要制定的文件:我们这里加入的是:F:\书籍\王勇Spring\Spring相关资料\spring-framework-2.0\dist\resources\spring-aop-2.0.xsd)-->Key Type(Schema Location), 再把Location中刚刚加上的文件的名字加到Key那个字符串的后面,注意加的的时候要加上"/":/spring-aop-2.0.xsd
*******
6.编写客户端
spring Ioc容器的关键点:
*必须将被管理的对象定义到spring配置文件中
*必须定义构造函数或setter方法,让spring将对象注入过来。
*spring Ioc(inversion )容器是依赖注入(DI:dependency injection ),控制反转
-------------------------------------------------------------------------
2.spring的基本属性和自定义属性编辑器注入:
*注意使用junit测试类的时候可以使用它的setUp()方法进行初始化,如我们测试spring的时候,每个方法都要用到beanFactory。所以我们可以再setUp()方法中初始化beanFactory。
public void serUp throws Exception{
BeanFactory facotry=new ClassPathXmlApplicationContext("ApplicationContext.xml");//通过classpath方式读取spring的配置文件//ApplicationContext.xml,配置文件可以写多个,如果有多个配置文件,那么可以//通过数据在读取,或者把配置文件的名字都命名为ApplicationContext-xx.xml,那//么就可以通过BeanFactory facotry=new ClassPathXmlApplicationContext//("ApplicationContext-*.xml")就可以读取所有的配置文件了。
}
*普通属性(String,int,list,map,数组等)注入可以参考开发手册的3.3章节(核心技术/容器/依赖/依赖注入).
**************
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<bean id="bean1" class="com.xiaojing.spring.Bean1">
<!-- int注入 -->
<property name="intvalue" value="1000"/>
<!--string注入 -->
<property name="stringvalue" value="lily"/>
<!-- list注入 -->
<property name="listvalue" >
<list>
<value>ab</value>
<value >cd</value>
<ref bean="bean2"/><!-- list集合中放有bean2对象,引用 -->
<value>ef</value>
<value>gh</value>
</list>
</property>
<!-- map注入 -->
<property name="mapvalue">
<map>
<entry><!-- map容器中放有bean2对象,引用 -->
<key><value>k1</value></key>
<ref bean="bean2"/>
</entry>
<entry key="k2" value="I love you">
</entry>
<entry>
<key><value>k3</value></key>
<value>520</value>
</entry>
</map>
</property>
<!-- 数组注入-->
<property name="arrayvalue">
<list>
<value>array1</value>
<value>array2</value>
<value>1233</value>
</list>
</property>
<!--set注入 -->
<property name="setvalue">
<set>
<value>set1</value>
<ref bean="bean2"/><!-- set容器中放有bean2对象,引用 -->
<value>set3</value>
</set>
</property>
</bean>
<bean id="bean2" class="com.xiaojing.spring.Bean2">
<property name="id">
<value>10010</value>
</property>
<property name="name" value="lucy"/>
</bean>
</beans>
**************
*什么是属性编辑器,作用?
1).自定义属性编辑器,spring配置文件中的字符串转换成相应的对象进行注入,spring已经有内置的属性编辑器,我们可以根据自己的需求定义属性编辑器,
2).如何定义属性编辑器?
a.继承属性编辑器类java.beans.PropertyEditorSupport,覆写setAsText()方法
b.将属性编辑器注册到org.springframework.beans.factory.config.customerEditorConfig类中的customEditors域成员的map中。
eg:日期要写属性编辑器才可以注入,属性编辑器类要继承属性编辑器支持类(java.beans.PropertyEditorSupport),并且覆写他的setAsText(String text)方法,并在该方法中通过this调用setValue()方法把转换后的值传进去:this.setValue(date),其中date为转换后的日期,text为配置文件中传入的日期字符串。然后在配置文件中将该类注入到org.springframework.beans.factory.config.customerEditorConfig类中的域成员customerEditors的map中,
--------
//自己的属性编辑器把字符串转换为Date类型:
package com.xiaojing.spring;
import java.beans.PropertyEditorSupport;
import java.util.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
public class UtilDataPropertyEditorsup extends PropertyEditorSupport {
private String format;
//写上set方法并在配置文件中配置该类的bean的时候加上<property name="formt" value="yyyy-mm-dd"/>那么下面转换的方法就不用写上format= "yyyy-mm-dd";了
public void setFormat(String format) {
this.format = format;
}
@Override
public void setAsText(String text) throws IllegalArgumentException {
//这里是没有在配置文件中配置format属性的值,如果配置了就不用在 写format了
// format= "yyyy-mm-dd";
System.out.println("text="+text);
try {
//将配置文件中的时间字符串转换为时间类型,这里的text其实就是配置文件中传入的字符串
SimpleDateFormat sdf=new SimpleDateFormat(format);
Date d=sdf.parse(text);
this.setValue(d);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
--------
<bean id="CustomEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry>
<key><value>java.util.Date</value></key><!-- 将字符串转换为date类型 -->
<!-- 引用com.xiaojing.spring.UtilDataPropertyEditorsup类作为该key所对应的value的值
<ref bean="udpe"/>
-->
<!-- 把自己写的属性编辑器类作为他的内部bean,因为就只有该bean引用它(com.xiaojing.spring.UtilDataPropertyEditorsup) -->
<bean class="com.xiaojing.spring.UtilDataPropertyEditorsup">
<property name="format" value="yyyy/mm/dd"></property>
</bean>
</entry>
</map>
</property>
</bean>
<!-- 可以把该bean作为内部bean放到CustomEditorConfigurer所对应的bean中
<bean id="udpe" class="com.xiaojing.spring.UtilDataPropertyEditorsup">
<property name="format" value="yyyy/mm/dd"></property>
</bean>
-->
<bean id="bean3" class="com.xiaojing.spring.Bean3HasData">
<property name="id" value="1"/>
<property name="name" value="小静"/>
<property name="createdate" value="2008/02/02"/><!-- 这里的日期要用到属性编辑器把string转换为date类型 -->
</bean>
--------
Bean3HasData:
int id;
String name;
Date createdate;
-------------------------------------------------------------------------
3.依赖注入的方式,可以采用:
*ref属性
*<ref>标签
*内部<bean>
-------------------------------------------------------------------------
4.如何建公共的属性定义描述出来:
a.通过<bean>标签定义公共的属性,并且指定属性abstract="true";
b.具有相同属性的类的<bean>标签中指定其parent="上面定义的公共属性中bean标签中的id属性"
eg:如有类:
Bean1:int id;Bean2 bean2;Bean3 bean3;Bean4 bean4;(也就是bean234都是bean1的域成员)
Bean2:int id;String name;String password;
Bean3:int id;String name;
bean4:int age;
类Bean2和Bean3有相同的属性id和name,并且id的值都为1000,name为jack,如果值不同的话,也可以再自己的类Bean2和Bean3中重新abbstract="true"那个bean中的property的value值
那么在配置文件中可以这样写:
---
<beans>
<bean id="bean1" class="com.xiaojing.spring.Bean1">
<property name="id" value="1000000"/>
【注意name属性里面是Bean1类中的域成员,ref写引用的那个类对应配置文件中<bean>标签的id,】
<property name="bean2" ref="b2"/>
<property name="bean3">
<ref bean="b3">
</property>
<property name="bean4" ref="b4"/>
</bean>
<bean id="commonbean" abstract="true">
<property name="id" value="1000"/>
<property name="name" value="jack">
</bean>
【加入bean2中的name域成员的值不为jack而是lucy那么我们就要重写该成员的值
即在里面加上<property name="name" value="lucy"/>
】
<bean id="b2" parent="commonbean" class="com.xiaojing.spring.Bean2">
<property name="password" value="123"/>
<property name="name" value="lucy"/>
</bean>
<bean id="b3" parent="commonbean" class="com.xiaojing.spring.Bean3">
</bean>
<bean id="b4" class="com.xiaojing.spring.Bean4">
<property name="age" value="45"/>
</bean>
</beans>
---
--------------------------------------------------------------------------
5.spring的bean的作用域:
scope可以取值:
*singleton:每次调用getBean的时候返回相同的实例,默认的是singleton;
*prototype:每次调用getBean的 时候返回不同的实例,线程安全;
<bean id="bean1" class="com.xiaojing.spring.Bean1" scope="singleton">
-------------------------------------------------------------------------
6.spring根据名称自动装配:有两种,一种是根据名称AutoWirebyName,另一种是根据类型AutoWirebyType,注意使用他们的时候都要在<beans>标签中配置defautl-autowire=""属性;如<beans default-autowire="buType(根据类型自动装配)/byName(根据姓名自动装配)">
--------------------------------------------------------------------------
7.代理模式:
静态代理:
1)写的代理类必须和被代理的类(也就是目标对象)实现同样的接口;要控制目标对象就必须具有目标对象的引用。
动态代理:
2)AOP的默认实现采用JDK的动态代理机制来实现的,把横切性的关注点单独拿出来,把散步在程序各个角落的东西拿出来模块化,模块化,模块化好处:模块化后就可以只单独维护模块就可以了
3)、动态代理类必须实现java.lang.reflect.InvocationHandler接口;
-----------
public class SecurityHandler implements InvocationHandler {
//定义目标对象,因为目标对象不知道具体是哪一个所以就用他们的父类object;
private Object targetObject;
//创建目标对象,创建代理类
public Object newProxy(Object targetObject){
//给目标对象赋值
this.targetObject=targetObject;
/*返回代理对象:第一个参数定义代理类的类加载器,得到目标对象的ClassLoader;
* 第二个参数为代理类要实现的接口列表:getInterfaces,第三个参数为指派方法调用的调用处理程序
*实现了InvocationHandler接口的类,我们这里就是他本身
*/
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),targetObject.getClass().getInterfaces(), this);
}
//实现了代理类的实例在调用方法时会调用该方法:在代理实例上处理方法调用并返回结果.所以我们可以在invoke()方法中调用像安全检查之类的方法。
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//在真正调用目标对象方法前调用检查方法:
this.securityCheck();
//由于目标对象的有些方法有返回值eg:findUser(),有的没有放回值eg:addUser();所以我们统一个返回值
Object result=null;
//有可能出现异常:
try{
//目标对象的实现
//proxy - 从中调用基础方法的对象,目标对象
//args - 用于方法调用的参数
result=method.invoke(this.targetObject, args);
}catch(Exception e){
e.printStackTrace();
throw new java.lang.RuntimeException(e);//继续将异常向上抛
}
return result;
}
//检查安全的方法
private void securityCheck(){
System.out.println("这是安全检查方法");
}
}
-----------
4)AOP:
a.横切性关注点(Cross cutting concern)是AOP的术语,模块化的那个类就是切面(Aspect)类,该类中的具体实现如安全检查方法在Aop术语中交advice(横切性关注点的实现),有多种advice,有在目标对象的方法执行之前执行该具体实现advice如先执行安全检查在执行目标对象的添加add()方法(Before advice),方法执行之后(after advice)等;过滤条件也就是什么时候用到那个目标对象上,用到目标对象上的哪个方法等在AOP术语中交切入点(Pointcut(add*)所以add*的方法都用到该到该横切面);把切面应用到目标对象(target object)的过程在AOP的术语是织入weave,连接点(在Spring中就是目标对象的方法)在AOP中叫joinpoint;代理对象在AOP中叫Proxy object;introduction可以动态的加方法。
b.spring AOP的实现:Spring的切入点模型使得切入点可以独立于通知类型进行重用,这就使得针对不同 advice使用相同的pointcut成为可能
I、采用注解的方式(采用Annotation的方式):
*加上jar包:
spring的依赖包
*spring_home/dist/spring.jar
*spring_home/lib/jakarta-commons/commons-logging.jar
*spring_home/lib/log4j/jog4j-1.2.14.jar
*spring_home/lib/aspectj/*.jar(这个是SPRING的Aop的jar包)
*、指定切面aspect:
在类的上面写上:@Aspect
-------------
*写上标识:
private void alladdMethod(){};//定义Poingtcut,Poingcut的名称就是alladdMethod,此方法不能有返回值和参数,该方法只是一个标识,我们不会执行。
-------------
*定义Pointcut,Ponintcut的内容是一个表达式,描述哪些对象的哪些方法(订阅joinpoint),在切面类中写上一个标识方法private void alladdMethod(){};,在标识方法上写:@Poincut("execution(* add*(..))")//该句话的意思是定义pointcut,第一个*标识不管是有返回值的还是没有返回值的都行,add*表示只要是以add开头的方法,..表示不管是有参数还是没有参数的都可以。
------------
*定义Advice:标识在哪个切入点Pointcut何处织入advice,在具体的方法(advice方法)上定义:
@Before(alladdMethod());//表示在目标对象的方法(Joinpoint)执行前执行advice.
private void checkSecutrity(){//具体的方法advice;
System.out.println("这是我们安全检测的方法advice");
}
-----------
*在配置文件中applicationContext.xml中配置:
首先加入标签指明使用注解(Annotation)方式:
<aop:aspectj-autoproxy/>
将Aspect类和目标对象配置到IOC容器(applicationContext.xml)中:
//这是aspect类
<bean id="securityHandler" class="com.xioajing.spring.SecurityHandler"/>
//这是目标对象
<bean id="userManager" class="com.xiaojing.spring.UserManagerImp"/>
----------
注意:在这种方法定义中,切入点的方法是不被执行的,它存在的目的仅仅是为了重用切入点。即:Adcice中通过切入点的方法名引用切入点。
--------------------------------------------
II.spring AOP的实现采用(静态文件方式)配置文件的方式:
在IOC容器中(applicationContex.xml文件中配置):
-----
//这是aspect类
<bean id="securityHandler" class="com.xioajing.spring.SecurityHandler"/>
//这是目标对象
<bean id="userManager" class="com.xiaojing.spring.UserManagerImp"/>
<aop:config>
<aop:aspect id="security" ref="securityHandler">
<aop:pointcut id="alladdMethod" expression="exectuion(* com.xiaojing.spring.UserManagerImpl.*)"/>
<aop:before method="checkSecurity"
pointcut-ref="alladdMethod"/>
</aop:aspect>
</aop:config>
-----
上面expression="execution(* com.xiaojing.spring.UserManagerImpl.*(..))"//表示advice应用到com.xiaojing.spring.UserManagerImpl类里的所有方法;
expression="execution(* com.xiaojing.spring.UserManagerImpl.add*(..))"//表示advice应用到com.xiaojing.spring.UserManagerImpl类里的所有以add开头的方法;expression="execution(* com.xiaojing.spring.UserManagerImpl.add*(..) || execution(* com.xiaojing.spring.UserManagerImpl.delete*(..))"//表示表示advice应用到com.xiaojing.spring.UserManagerImpl类里的所有以add和delete开头的方法.
<aop:aspect id="security" ref="securityHandler">,ref中的值是aspect类所对应<bean>标签的id的值,<aop:pointcut id="alladdMethod" ,pointcut中的id的值是写的一个标识,自己写的;<aop:before method="checkSecurity" pointcut-ref="alladdMethod"/>,before表示在joinpoint之前执行checkSecurity(advice)方法,checkSecurity是在Aspect类中的具体实现的方法,pointcut-ref中的值是<aop:pointcut>中id的值,表示执行哪个Pointcut。
--------------------------------------------
III、spring 对AOP的支持:
*Aspect 默认情况下不用实现接口,但对应目标对象(UserMangerImpl.java)在默认情况下必须实现接口,如果没有实现必须引入CGLib库,如果没有引入CGLIB库那么就会报错AopConfigException。
*我们可以通过在Advice方法中添加一个JointPoint参数,目标对象的信息会由spring自动传入,从JoinPoint中可以取得目标对象方法(joinpoint)的参数值、方法名等待。JoinPoint 的实例jp.getArgs()得到的是Object[]对象数组,该数组中放的是目标的对象中调用方法的参数;jp.getSignature().getName();得到被调用方法的名称。
-------------------------------------------------------------------------
8.JDK的动态代理和CGLib:
1).如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP;
2)如果目标对象实现了接口,可以强制使用CGLIB实现AOP:
a.如何强制使用CGLIB实现AOP?:
*添加CGLIB库:spring_home/cglib/*.jar.
*在spring配置文件(applicationContext.xml)中加入:
<aop:aspectj-autoproxy proxy-target-class="true"/>
3)、如果目标对象没有实现接口,必须使用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换。
总结:JDK动态代理和CGLIB字节码生成的区别:
*JDK动态代理只能对实现了接口的类生成代理,而不能针对类;
*CGLIB是针对类实现代理,主要是对指定的类生成一个子类作为代理,覆盖其中的 方法, 因为是继承,所以该类或方法最好不要声明成final
-------------------------------------------------------------------------9.hibernate和spring的集成:完成声明式事务的配置:
1).getCurrentSession()与openSession()得到的session的区别?
*采用getCurrentSession()创建的session会绑定到当前的线程中,而采用openSession()创建的session则不会;
*采用getCurrentSession()创建的session在提交(commmit)或者回滚(rollback)的时候自动关闭,而采用openSession()创建的session则必须手动关闭;
2)、使用getCurrentSession()需要在hibernate.cfg.xml文件中加入如下配置:
a.如果使用的是本地事务(JDBC事务,就是只有一个数据库等),加入如下:
<property name="hibenrante.current_session_context_class">thread</property>
b.如果使用的是全局事务(jta事务,就是不只有一个数据库或许有几个数据库,或者有其它的一些可以回滚事务的资源等),加入如下:
<property name="hibenrante.current_session_context_class">jta</property>
3).事务的传播特性,隔离级别:
4).hibernate和spring的集成:
配置:
在spring的配置文件中applicationContext.xml文件中配置:
a、配置sessionFactory,把配置文件hibernate.cfg.xml注入到LocalSessionFactory类中的configLocation属性中:
-----
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactory">
<property name="configLocation">
<value>classpath:hibernante.cfg.xml</value>
</property>
</bean>
-----
上面代码中<bean>中的id是我们自己起的名字,但是一般都叫sessionFactory;
<property name="configLocation">中的configLocation是org.springframework.orm.hibernate3.LocalSessionFactory类的域成员;<value>采用classpath:协议注入,hibernante.cfg.xml是hibenrante的配置文件名称;
********************
b、配置事务管理器,把sessionFactory注入到HibernateTransactionManager类中的SessionFacotory属性中,让他管理sessionFactory:
----
<bean id="transactionmanager" class="org.springframeword.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" >
<ref bean="sessionFactory"/>
</property>
</bena>
----
上面代码中,id="transactionmanager" :id的值是自己起的名字,property中name属性的值是HibernateTransactionManager类的域成员,<ref>标签中bean的值是自己配置的sessionFactory中<bean>标签id的值。
*******************
c、配制事务传播特性;
----
<tx:advice id="txadvice" transaction-manager="tanasactionmanager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="modify*" propagation="REQUIRED"/>
<tx:method name="*" read-only="ture"/>
</tx:attributes>
</tx:advice>
----
上面代码中,<tc:advice>标签中的id中的值是自己起的名字,transaction-manager中的值是自己配置的事物管理器<bean>标签中id的值,<tx:method name="add*/modify*/delete*" propagation="REQUIRED"/><tx:method name="*" read-only="ture"/>的意思分别是以add或者modify或者delete开头的方法的事物传
播特性是required,其余的方法都是只读。
****************************
d.哪些类哪些方法参与事务,即:配置aspect;
------
<aop:config>
<aop:pointcut name="allmanagermethod" expression="execution(* com.xiaojing.mamager.*(..))"/>
<aop:advisor pointcut-ref="allmanagermethod" advice-ref="txadvice"/>
</aop:config>
------
上面代码中<aop:pointcut>标签中name的值是自己给pointcut起的名字,expression中的以上是com.xiaojing.mamager包中所有类的所有方法都是用事物。<aop:abvisor>相当于<aop:aspect>标签,这里的<adisor>标签是spring特定的,里面pointcut-ref的值是<aop:pointcut>中name的值,advic-ref的值是事物传播特性中<tx:advice>中id的值。
*******************************
e.那些要使用到SessionFacory或this.getHibernateTemplate()(用spring的话可以用他的this.getHibernateTemplate()获得sessionFactory)的类在spring的配置文件中都要把SessionFactory注入进去。即:
<property name="sessionFactory" ref="sessionFactory"/>,并且该类要继承HibernateDaoSupport类,这里id中的sessionFactory是HibernateDaoSupport类的域成员,ref中的sessionFactory是自己配置sessionFactory的<baen>标签中id属性的值。
f.编写业务逻辑方法:
*那么这些具有该方法的类必须继承HibernateDaoSupport类,使用HibernateTemplate是Hibernate Session的轻量级封装
*默认情况下运行期异常(RunTimeException)才会回滚,包括继承了RunTimeException的子类也回滚,普通异常默认情况下是不回滚的。
*编写业务逻辑方法是,最好将异常一直向上抛,在表示层(struts那块)做处理;
*关于事务边界的设置(比如表示层要访问的地方),通常设置到业务层,不要添加到DAO上。
--------
注意通过spring管理SessionFactory,回滚事务默认是回滚运行期异常,也就是runTimeException。
--------------------------------------------------------------------------
10.AOP的总结:AOP关注横切性的关注点,我们使用AOP主要是完成声明式事物,注意他里面的术语:Cross cutting concern,Aspect,Advice,Pointcut,Joinpoint(注意在spring只支持方法级的Joinpoint),Weave(织入:advice应用到Joinpoint的过程),Target Object,Proxy,Introduction
-------------------------------------------------------------------------11、spring+struts的集成(第一种集成方案)
原理:在Action中取得BeanFactory对象,然后通过BeanFactory获得业务逻辑对象;
步骤:
1).spring和struts依赖库配置:
*配置struts
--拷贝struts类库和jstl类库
--修改web.xml文件来配置ActionServlet
--提供struts-config.xml文件
--提供国际化资源文件
*配置spring
--拷贝spring类库
--提供spring配置文件applicationContext.xml;
2).在struts的Action中调用如下代码取得BeanFactory
创建文件
SessionFactory factory=webapplicationContextUtils.getRequiredApplicationContext(required.getSession.getContext);
3).通过beanFactory取得业务对象,调用业务逻辑方法。
--------------------------------------------------------------------------
12、spring+struts的集成(第二种集成方案)
原理:将业务逻辑对象通过spring注入到Action中,从而避免在Aciton类中直接代码查找;
步骤:
1).spring和struts依赖库配置:
*配置struts
--拷贝struts类库和jstl类库
--修改web.xml文件来配置ActionServlet
--提供struts-config.xml文件
--提供国际化资源文件
*配置spring
--拷贝spring类库
--提供spring配置文件applicationContext.xml;
2).
*因为action需要调用业务逻辑方法,所以需要在aciton中提供setter方法,让 spring把业务逻辑对象注入过来。
*在struts-config.xml文件中配置action:
<action>标签中的type属性需要修改为spring提供的action的代理,代理的action:
DelegatingActionProxy是一个代理的action,主要作用是取得BeanFactory,然后根据<action>标签中path属性值到IoC容器中取得本次请求对应的Action;
*在spring配置文件中需要定义struts的Action,如:
------
<bean name="/login" class="com.xiaojing.usermagr.actions.LoginAction" scope="prototype">
<property name="userManager" ref="userManager"/>
</bean>
-------
上面代码中【注意】:
*<bean>标签中使用一定使用name属性,并且name属性的值要和sturts-config.xml文件中<action>标签中的path属性值一模一样。
*、必须注入业务逻辑对象,eg:ref="userManager",这里<property>标签中name属性的值是LoginAction类的域成员,ref属性的值是UserManagerImpl类对应<bean>标签中id的值。。
*建议将scope设置为Prototype,这样就避免了struts Action的线程安全问题。不在是单实例,而是每次过来创建一个实例。
-------------------------------------------------------------------------13.struts-spring-hibernate集成:
*在配置sessionfactory的时候:<!-- 配置sessionFactory,如果hibernate.cfg.xml是放在src写,那么就采用classpath:hibernate.cfg.xml的形式初始化配置文件,如果放在web-inf下就采用下面的方式 -->
-----------
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation" >
<value>
/WEB-INF/hibernate.cfg.xml
</value>
</property>
</bean>
-----------
*不要忘记加载数据库的jar包
步骤:
先加人jar包,(这里采用的是手动:Spring(spring.jar,log4j.jarjakarta-commons/commons-logging.jar)--hibernante(hibernate3.jar,lib/*.jar,数据库驱动)--sturts(sturs的所有jar包)--数据库驱动的jar包(如果hibernate没有加的话));
【hiberante】关联的原码和配置文件分别是:hibernate-3.2.0.ga.zip;hibernante.cfg.xml;
【spring】关联的原码是:F:\书籍\王勇Spring\Spring相关资料\spring-framework-2.0\dist\spring-src.zip;applicationContext.xml;(注意spring关联的只能是springjar包中的spring文件才可以)
【struts】关联的原码是:F:\书籍\王勇struts\JSTL_BeanUtils_Struts相关资料\struts_install\struts-1.2.9-src.zip,struts-cfg.xml;
-------------------------------------------------------------------------14.spring的总结:Ioc就相当于工厂,我们可以通过Ioc拿到对象,叫控制反转。IoC有两种实现方式:依赖查找和依赖注入。Spring实现是依赖注入。
--------------------------------------------------------------------------
15.oracle数据库的driver:Class.forName("oracle.jdbc.driver.OracleDriver");
oracle数据库的URL:String url="jdbc:oracle:thin:@localhost:1521:orcl";//其中1521是oracle的端口号,orcl是连接的数据库名(如我自己建立的oracle数据库的名字是orcl)
oracle数据库要加的jar包是ojdbc14.jar(有两个)
-------------------------------------------
16.spring的配置文件applicationContext.xml文件中: <ref bean="mybean"/>和
<ref local="mybean"/> 的区别:
有多个spring的配置文件,mybean不在当前xml中用<ref bean="mybean"/>
步骤:window-->preferences-->java-->user libraries-->new-->给要加的包命名-->add jars-->
1)、spring的依赖包
*spring_home/dist/spring.jar
*spring_home/lib/jakarta-commons/commons-logging.jar
*soring_home/lob/log4j/jog4j-1.2.14.jar
2).拷贝spring配置文件到src下
3).拷贝log4j配置文件到src下
4).在UserManagerImpl中提供构造函数(或set方法),spring将实例化好的UserDao实现诸如给我们
5.让spring关联我们的对象创建和依赖,必须在sprin配置文件(applcationContext.xml)中进行定义,如果在配置文件中打印的时候没有提示,可以加上相应文件的配置提示,eg加入AOP的提示文件加入方法如下:
*******
window-->preferrnces-->MyEclipse-->Files and Editors-->XML Catalog-->User Specified Entries-->add-->Key Type(选择URI),Location(File System加入要制定的文件:我们这里加入的是:F:\书籍\王勇Spring\Spring相关资料\spring-framework-2.0\dist\resources\spring-aop-2.0.xsd)-->Key Type(Schema Location), 再把Location中刚刚加上的文件的名字加到Key那个字符串的后面,注意加的的时候要加上"/":/spring-aop-2.0.xsd
*******
6.编写客户端
spring Ioc容器的关键点:
*必须将被管理的对象定义到spring配置文件中
*必须定义构造函数或setter方法,让spring将对象注入过来。
*spring Ioc(inversion )容器是依赖注入(DI:dependency injection ),控制反转
-------------------------------------------------------------------------
2.spring的基本属性和自定义属性编辑器注入:
*注意使用junit测试类的时候可以使用它的setUp()方法进行初始化,如我们测试spring的时候,每个方法都要用到beanFactory。所以我们可以再setUp()方法中初始化beanFactory。
public void serUp throws Exception{
BeanFactory facotry=new ClassPathXmlApplicationContext("ApplicationContext.xml");//通过classpath方式读取spring的配置文件//ApplicationContext.xml,配置文件可以写多个,如果有多个配置文件,那么可以//通过数据在读取,或者把配置文件的名字都命名为ApplicationContext-xx.xml,那//么就可以通过BeanFactory facotry=new ClassPathXmlApplicationContext//("ApplicationContext-*.xml")就可以读取所有的配置文件了。
}
*普通属性(String,int,list,map,数组等)注入可以参考开发手册的3.3章节(核心技术/容器/依赖/依赖注入).
**************
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<bean id="bean1" class="com.xiaojing.spring.Bean1">
<!-- int注入 -->
<property name="intvalue" value="1000"/>
<!--string注入 -->
<property name="stringvalue" value="lily"/>
<!-- list注入 -->
<property name="listvalue" >
<list>
<value>ab</value>
<value >cd</value>
<ref bean="bean2"/><!-- list集合中放有bean2对象,引用 -->
<value>ef</value>
<value>gh</value>
</list>
</property>
<!-- map注入 -->
<property name="mapvalue">
<map>
<entry><!-- map容器中放有bean2对象,引用 -->
<key><value>k1</value></key>
<ref bean="bean2"/>
</entry>
<entry key="k2" value="I love you">
</entry>
<entry>
<key><value>k3</value></key>
<value>520</value>
</entry>
</map>
</property>
<!-- 数组注入-->
<property name="arrayvalue">
<list>
<value>array1</value>
<value>array2</value>
<value>1233</value>
</list>
</property>
<!--set注入 -->
<property name="setvalue">
<set>
<value>set1</value>
<ref bean="bean2"/><!-- set容器中放有bean2对象,引用 -->
<value>set3</value>
</set>
</property>
</bean>
<bean id="bean2" class="com.xiaojing.spring.Bean2">
<property name="id">
<value>10010</value>
</property>
<property name="name" value="lucy"/>
</bean>
</beans>
**************
*什么是属性编辑器,作用?
1).自定义属性编辑器,spring配置文件中的字符串转换成相应的对象进行注入,spring已经有内置的属性编辑器,我们可以根据自己的需求定义属性编辑器,
2).如何定义属性编辑器?
a.继承属性编辑器类java.beans.PropertyEditorSupport,覆写setAsText()方法
b.将属性编辑器注册到org.springframework.beans.factory.config.customerEditorConfig类中的customEditors域成员的map中。
eg:日期要写属性编辑器才可以注入,属性编辑器类要继承属性编辑器支持类(java.beans.PropertyEditorSupport),并且覆写他的setAsText(String text)方法,并在该方法中通过this调用setValue()方法把转换后的值传进去:this.setValue(date),其中date为转换后的日期,text为配置文件中传入的日期字符串。然后在配置文件中将该类注入到org.springframework.beans.factory.config.customerEditorConfig类中的域成员customerEditors的map中,
--------
//自己的属性编辑器把字符串转换为Date类型:
package com.xiaojing.spring;
import java.beans.PropertyEditorSupport;
import java.util.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
public class UtilDataPropertyEditorsup extends PropertyEditorSupport {
private String format;
//写上set方法并在配置文件中配置该类的bean的时候加上<property name="formt" value="yyyy-mm-dd"/>那么下面转换的方法就不用写上format= "yyyy-mm-dd";了
public void setFormat(String format) {
this.format = format;
}
@Override
public void setAsText(String text) throws IllegalArgumentException {
//这里是没有在配置文件中配置format属性的值,如果配置了就不用在 写format了
// format= "yyyy-mm-dd";
System.out.println("text="+text);
try {
//将配置文件中的时间字符串转换为时间类型,这里的text其实就是配置文件中传入的字符串
SimpleDateFormat sdf=new SimpleDateFormat(format);
Date d=sdf.parse(text);
this.setValue(d);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
--------
<bean id="CustomEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry>
<key><value>java.util.Date</value></key><!-- 将字符串转换为date类型 -->
<!-- 引用com.xiaojing.spring.UtilDataPropertyEditorsup类作为该key所对应的value的值
<ref bean="udpe"/>
-->
<!-- 把自己写的属性编辑器类作为他的内部bean,因为就只有该bean引用它(com.xiaojing.spring.UtilDataPropertyEditorsup) -->
<bean class="com.xiaojing.spring.UtilDataPropertyEditorsup">
<property name="format" value="yyyy/mm/dd"></property>
</bean>
</entry>
</map>
</property>
</bean>
<!-- 可以把该bean作为内部bean放到CustomEditorConfigurer所对应的bean中
<bean id="udpe" class="com.xiaojing.spring.UtilDataPropertyEditorsup">
<property name="format" value="yyyy/mm/dd"></property>
</bean>
-->
<bean id="bean3" class="com.xiaojing.spring.Bean3HasData">
<property name="id" value="1"/>
<property name="name" value="小静"/>
<property name="createdate" value="2008/02/02"/><!-- 这里的日期要用到属性编辑器把string转换为date类型 -->
</bean>
--------
Bean3HasData:
int id;
String name;
Date createdate;
-------------------------------------------------------------------------
3.依赖注入的方式,可以采用:
*ref属性
*<ref>标签
*内部<bean>
-------------------------------------------------------------------------
4.如何建公共的属性定义描述出来:
a.通过<bean>标签定义公共的属性,并且指定属性abstract="true";
b.具有相同属性的类的<bean>标签中指定其parent="上面定义的公共属性中bean标签中的id属性"
eg:如有类:
Bean1:int id;Bean2 bean2;Bean3 bean3;Bean4 bean4;(也就是bean234都是bean1的域成员)
Bean2:int id;String name;String password;
Bean3:int id;String name;
bean4:int age;
类Bean2和Bean3有相同的属性id和name,并且id的值都为1000,name为jack,如果值不同的话,也可以再自己的类Bean2和Bean3中重新abbstract="true"那个bean中的property的value值
那么在配置文件中可以这样写:
---
<beans>
<bean id="bean1" class="com.xiaojing.spring.Bean1">
<property name="id" value="1000000"/>
【注意name属性里面是Bean1类中的域成员,ref写引用的那个类对应配置文件中<bean>标签的id,】
<property name="bean2" ref="b2"/>
<property name="bean3">
<ref bean="b3">
</property>
<property name="bean4" ref="b4"/>
</bean>
<bean id="commonbean" abstract="true">
<property name="id" value="1000"/>
<property name="name" value="jack">
</bean>
【加入bean2中的name域成员的值不为jack而是lucy那么我们就要重写该成员的值
即在里面加上<property name="name" value="lucy"/>
】
<bean id="b2" parent="commonbean" class="com.xiaojing.spring.Bean2">
<property name="password" value="123"/>
<property name="name" value="lucy"/>
</bean>
<bean id="b3" parent="commonbean" class="com.xiaojing.spring.Bean3">
</bean>
<bean id="b4" class="com.xiaojing.spring.Bean4">
<property name="age" value="45"/>
</bean>
</beans>
---
--------------------------------------------------------------------------
5.spring的bean的作用域:
scope可以取值:
*singleton:每次调用getBean的时候返回相同的实例,默认的是singleton;
*prototype:每次调用getBean的 时候返回不同的实例,线程安全;
<bean id="bean1" class="com.xiaojing.spring.Bean1" scope="singleton">
-------------------------------------------------------------------------
6.spring根据名称自动装配:有两种,一种是根据名称AutoWirebyName,另一种是根据类型AutoWirebyType,注意使用他们的时候都要在<beans>标签中配置defautl-autowire=""属性;如<beans default-autowire="buType(根据类型自动装配)/byName(根据姓名自动装配)">
--------------------------------------------------------------------------
7.代理模式:
静态代理:
1)写的代理类必须和被代理的类(也就是目标对象)实现同样的接口;要控制目标对象就必须具有目标对象的引用。
动态代理:
2)AOP的默认实现采用JDK的动态代理机制来实现的,把横切性的关注点单独拿出来,把散步在程序各个角落的东西拿出来模块化,模块化,模块化好处:模块化后就可以只单独维护模块就可以了
3)、动态代理类必须实现java.lang.reflect.InvocationHandler接口;
-----------
public class SecurityHandler implements InvocationHandler {
//定义目标对象,因为目标对象不知道具体是哪一个所以就用他们的父类object;
private Object targetObject;
//创建目标对象,创建代理类
public Object newProxy(Object targetObject){
//给目标对象赋值
this.targetObject=targetObject;
/*返回代理对象:第一个参数定义代理类的类加载器,得到目标对象的ClassLoader;
* 第二个参数为代理类要实现的接口列表:getInterfaces,第三个参数为指派方法调用的调用处理程序
*实现了InvocationHandler接口的类,我们这里就是他本身
*/
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),targetObject.getClass().getInterfaces(), this);
}
//实现了代理类的实例在调用方法时会调用该方法:在代理实例上处理方法调用并返回结果.所以我们可以在invoke()方法中调用像安全检查之类的方法。
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//在真正调用目标对象方法前调用检查方法:
this.securityCheck();
//由于目标对象的有些方法有返回值eg:findUser(),有的没有放回值eg:addUser();所以我们统一个返回值
Object result=null;
//有可能出现异常:
try{
//目标对象的实现
//proxy - 从中调用基础方法的对象,目标对象
//args - 用于方法调用的参数
result=method.invoke(this.targetObject, args);
}catch(Exception e){
e.printStackTrace();
throw new java.lang.RuntimeException(e);//继续将异常向上抛
}
return result;
}
//检查安全的方法
private void securityCheck(){
System.out.println("这是安全检查方法");
}
}
-----------
4)AOP:
a.横切性关注点(Cross cutting concern)是AOP的术语,模块化的那个类就是切面(Aspect)类,该类中的具体实现如安全检查方法在Aop术语中交advice(横切性关注点的实现),有多种advice,有在目标对象的方法执行之前执行该具体实现advice如先执行安全检查在执行目标对象的添加add()方法(Before advice),方法执行之后(after advice)等;过滤条件也就是什么时候用到那个目标对象上,用到目标对象上的哪个方法等在AOP术语中交切入点(Pointcut(add*)所以add*的方法都用到该到该横切面);把切面应用到目标对象(target object)的过程在AOP的术语是织入weave,连接点(在Spring中就是目标对象的方法)在AOP中叫joinpoint;代理对象在AOP中叫Proxy object;introduction可以动态的加方法。
b.spring AOP的实现:Spring的切入点模型使得切入点可以独立于通知类型进行重用,这就使得针对不同 advice使用相同的pointcut成为可能
I、采用注解的方式(采用Annotation的方式):
*加上jar包:
spring的依赖包
*spring_home/dist/spring.jar
*spring_home/lib/jakarta-commons/commons-logging.jar
*spring_home/lib/log4j/jog4j-1.2.14.jar
*spring_home/lib/aspectj/*.jar(这个是SPRING的Aop的jar包)
*、指定切面aspect:
在类的上面写上:@Aspect
-------------
*写上标识:
private void alladdMethod(){};//定义Poingtcut,Poingcut的名称就是alladdMethod,此方法不能有返回值和参数,该方法只是一个标识,我们不会执行。
-------------
*定义Pointcut,Ponintcut的内容是一个表达式,描述哪些对象的哪些方法(订阅joinpoint),在切面类中写上一个标识方法private void alladdMethod(){};,在标识方法上写:@Poincut("execution(* add*(..))")//该句话的意思是定义pointcut,第一个*标识不管是有返回值的还是没有返回值的都行,add*表示只要是以add开头的方法,..表示不管是有参数还是没有参数的都可以。
------------
*定义Advice:标识在哪个切入点Pointcut何处织入advice,在具体的方法(advice方法)上定义:
@Before(alladdMethod());//表示在目标对象的方法(Joinpoint)执行前执行advice.
private void checkSecutrity(){//具体的方法advice;
System.out.println("这是我们安全检测的方法advice");
}
-----------
*在配置文件中applicationContext.xml中配置:
首先加入标签指明使用注解(Annotation)方式:
<aop:aspectj-autoproxy/>
将Aspect类和目标对象配置到IOC容器(applicationContext.xml)中:
//这是aspect类
<bean id="securityHandler" class="com.xioajing.spring.SecurityHandler"/>
//这是目标对象
<bean id="userManager" class="com.xiaojing.spring.UserManagerImp"/>
----------
注意:在这种方法定义中,切入点的方法是不被执行的,它存在的目的仅仅是为了重用切入点。即:Adcice中通过切入点的方法名引用切入点。
--------------------------------------------
II.spring AOP的实现采用(静态文件方式)配置文件的方式:
在IOC容器中(applicationContex.xml文件中配置):
-----
//这是aspect类
<bean id="securityHandler" class="com.xioajing.spring.SecurityHandler"/>
//这是目标对象
<bean id="userManager" class="com.xiaojing.spring.UserManagerImp"/>
<aop:config>
<aop:aspect id="security" ref="securityHandler">
<aop:pointcut id="alladdMethod" expression="exectuion(* com.xiaojing.spring.UserManagerImpl.*)"/>
<aop:before method="checkSecurity"
pointcut-ref="alladdMethod"/>
</aop:aspect>
</aop:config>
-----
上面expression="execution(* com.xiaojing.spring.UserManagerImpl.*(..))"//表示advice应用到com.xiaojing.spring.UserManagerImpl类里的所有方法;
expression="execution(* com.xiaojing.spring.UserManagerImpl.add*(..))"//表示advice应用到com.xiaojing.spring.UserManagerImpl类里的所有以add开头的方法;expression="execution(* com.xiaojing.spring.UserManagerImpl.add*(..) || execution(* com.xiaojing.spring.UserManagerImpl.delete*(..))"//表示表示advice应用到com.xiaojing.spring.UserManagerImpl类里的所有以add和delete开头的方法.
<aop:aspect id="security" ref="securityHandler">,ref中的值是aspect类所对应<bean>标签的id的值,<aop:pointcut id="alladdMethod" ,pointcut中的id的值是写的一个标识,自己写的;<aop:before method="checkSecurity" pointcut-ref="alladdMethod"/>,before表示在joinpoint之前执行checkSecurity(advice)方法,checkSecurity是在Aspect类中的具体实现的方法,pointcut-ref中的值是<aop:pointcut>中id的值,表示执行哪个Pointcut。
--------------------------------------------
III、spring 对AOP的支持:
*Aspect 默认情况下不用实现接口,但对应目标对象(UserMangerImpl.java)在默认情况下必须实现接口,如果没有实现必须引入CGLib库,如果没有引入CGLIB库那么就会报错AopConfigException。
*我们可以通过在Advice方法中添加一个JointPoint参数,目标对象的信息会由spring自动传入,从JoinPoint中可以取得目标对象方法(joinpoint)的参数值、方法名等待。JoinPoint 的实例jp.getArgs()得到的是Object[]对象数组,该数组中放的是目标的对象中调用方法的参数;jp.getSignature().getName();得到被调用方法的名称。
-------------------------------------------------------------------------
8.JDK的动态代理和CGLib:
1).如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP;
2)如果目标对象实现了接口,可以强制使用CGLIB实现AOP:
a.如何强制使用CGLIB实现AOP?:
*添加CGLIB库:spring_home/cglib/*.jar.
*在spring配置文件(applicationContext.xml)中加入:
<aop:aspectj-autoproxy proxy-target-class="true"/>
3)、如果目标对象没有实现接口,必须使用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换。
总结:JDK动态代理和CGLIB字节码生成的区别:
*JDK动态代理只能对实现了接口的类生成代理,而不能针对类;
*CGLIB是针对类实现代理,主要是对指定的类生成一个子类作为代理,覆盖其中的 方法, 因为是继承,所以该类或方法最好不要声明成final
-------------------------------------------------------------------------9.hibernate和spring的集成:完成声明式事务的配置:
1).getCurrentSession()与openSession()得到的session的区别?
*采用getCurrentSession()创建的session会绑定到当前的线程中,而采用openSession()创建的session则不会;
*采用getCurrentSession()创建的session在提交(commmit)或者回滚(rollback)的时候自动关闭,而采用openSession()创建的session则必须手动关闭;
2)、使用getCurrentSession()需要在hibernate.cfg.xml文件中加入如下配置:
a.如果使用的是本地事务(JDBC事务,就是只有一个数据库等),加入如下:
<property name="hibenrante.current_session_context_class">thread</property>
b.如果使用的是全局事务(jta事务,就是不只有一个数据库或许有几个数据库,或者有其它的一些可以回滚事务的资源等),加入如下:
<property name="hibenrante.current_session_context_class">jta</property>
3).事务的传播特性,隔离级别:
4).hibernate和spring的集成:
配置:
在spring的配置文件中applicationContext.xml文件中配置:
a、配置sessionFactory,把配置文件hibernate.cfg.xml注入到LocalSessionFactory类中的configLocation属性中:
-----
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactory">
<property name="configLocation">
<value>classpath:hibernante.cfg.xml</value>
</property>
</bean>
-----
上面代码中<bean>中的id是我们自己起的名字,但是一般都叫sessionFactory;
<property name="configLocation">中的configLocation是org.springframework.orm.hibernate3.LocalSessionFactory类的域成员;<value>采用classpath:协议注入,hibernante.cfg.xml是hibenrante的配置文件名称;
********************
b、配置事务管理器,把sessionFactory注入到HibernateTransactionManager类中的SessionFacotory属性中,让他管理sessionFactory:
----
<bean id="transactionmanager" class="org.springframeword.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" >
<ref bean="sessionFactory"/>
</property>
</bena>
----
上面代码中,id="transactionmanager" :id的值是自己起的名字,property中name属性的值是HibernateTransactionManager类的域成员,<ref>标签中bean的值是自己配置的sessionFactory中<bean>标签id的值。
*******************
c、配制事务传播特性;
----
<tx:advice id="txadvice" transaction-manager="tanasactionmanager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="modify*" propagation="REQUIRED"/>
<tx:method name="*" read-only="ture"/>
</tx:attributes>
</tx:advice>
----
上面代码中,<tc:advice>标签中的id中的值是自己起的名字,transaction-manager中的值是自己配置的事物管理器<bean>标签中id的值,<tx:method name="add*/modify*/delete*" propagation="REQUIRED"/><tx:method name="*" read-only="ture"/>的意思分别是以add或者modify或者delete开头的方法的事物传
播特性是required,其余的方法都是只读。
****************************
d.哪些类哪些方法参与事务,即:配置aspect;
------
<aop:config>
<aop:pointcut name="allmanagermethod" expression="execution(* com.xiaojing.mamager.*(..))"/>
<aop:advisor pointcut-ref="allmanagermethod" advice-ref="txadvice"/>
</aop:config>
------
上面代码中<aop:pointcut>标签中name的值是自己给pointcut起的名字,expression中的以上是com.xiaojing.mamager包中所有类的所有方法都是用事物。<aop:abvisor>相当于<aop:aspect>标签,这里的<adisor>标签是spring特定的,里面pointcut-ref的值是<aop:pointcut>中name的值,advic-ref的值是事物传播特性中<tx:advice>中id的值。
*******************************
e.那些要使用到SessionFacory或this.getHibernateTemplate()(用spring的话可以用他的this.getHibernateTemplate()获得sessionFactory)的类在spring的配置文件中都要把SessionFactory注入进去。即:
<property name="sessionFactory" ref="sessionFactory"/>,并且该类要继承HibernateDaoSupport类,这里id中的sessionFactory是HibernateDaoSupport类的域成员,ref中的sessionFactory是自己配置sessionFactory的<baen>标签中id属性的值。
f.编写业务逻辑方法:
*那么这些具有该方法的类必须继承HibernateDaoSupport类,使用HibernateTemplate是Hibernate Session的轻量级封装
*默认情况下运行期异常(RunTimeException)才会回滚,包括继承了RunTimeException的子类也回滚,普通异常默认情况下是不回滚的。
*编写业务逻辑方法是,最好将异常一直向上抛,在表示层(struts那块)做处理;
*关于事务边界的设置(比如表示层要访问的地方),通常设置到业务层,不要添加到DAO上。
--------
注意通过spring管理SessionFactory,回滚事务默认是回滚运行期异常,也就是runTimeException。
--------------------------------------------------------------------------
10.AOP的总结:AOP关注横切性的关注点,我们使用AOP主要是完成声明式事物,注意他里面的术语:Cross cutting concern,Aspect,Advice,Pointcut,Joinpoint(注意在spring只支持方法级的Joinpoint),Weave(织入:advice应用到Joinpoint的过程),Target Object,Proxy,Introduction
-------------------------------------------------------------------------11、spring+struts的集成(第一种集成方案)
原理:在Action中取得BeanFactory对象,然后通过BeanFactory获得业务逻辑对象;
步骤:
1).spring和struts依赖库配置:
*配置struts
--拷贝struts类库和jstl类库
--修改web.xml文件来配置ActionServlet
--提供struts-config.xml文件
--提供国际化资源文件
*配置spring
--拷贝spring类库
--提供spring配置文件applicationContext.xml;
2).在struts的Action中调用如下代码取得BeanFactory
创建文件
SessionFactory factory=webapplicationContextUtils.getRequiredApplicationContext(required.getSession.getContext);
3).通过beanFactory取得业务对象,调用业务逻辑方法。
--------------------------------------------------------------------------
12、spring+struts的集成(第二种集成方案)
原理:将业务逻辑对象通过spring注入到Action中,从而避免在Aciton类中直接代码查找;
步骤:
1).spring和struts依赖库配置:
*配置struts
--拷贝struts类库和jstl类库
--修改web.xml文件来配置ActionServlet
--提供struts-config.xml文件
--提供国际化资源文件
*配置spring
--拷贝spring类库
--提供spring配置文件applicationContext.xml;
2).
*因为action需要调用业务逻辑方法,所以需要在aciton中提供setter方法,让 spring把业务逻辑对象注入过来。
*在struts-config.xml文件中配置action:
<action>标签中的type属性需要修改为spring提供的action的代理,代理的action:
DelegatingActionProxy是一个代理的action,主要作用是取得BeanFactory,然后根据<action>标签中path属性值到IoC容器中取得本次请求对应的Action;
*在spring配置文件中需要定义struts的Action,如:
------
<bean name="/login" class="com.xiaojing.usermagr.actions.LoginAction" scope="prototype">
<property name="userManager" ref="userManager"/>
</bean>
-------
上面代码中【注意】:
*<bean>标签中使用一定使用name属性,并且name属性的值要和sturts-config.xml文件中<action>标签中的path属性值一模一样。
*、必须注入业务逻辑对象,eg:ref="userManager",这里<property>标签中name属性的值是LoginAction类的域成员,ref属性的值是UserManagerImpl类对应<bean>标签中id的值。。
*建议将scope设置为Prototype,这样就避免了struts Action的线程安全问题。不在是单实例,而是每次过来创建一个实例。
-------------------------------------------------------------------------13.struts-spring-hibernate集成:
*在配置sessionfactory的时候:<!-- 配置sessionFactory,如果hibernate.cfg.xml是放在src写,那么就采用classpath:hibernate.cfg.xml的形式初始化配置文件,如果放在web-inf下就采用下面的方式 -->
-----------
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation" >
<value>
/WEB-INF/hibernate.cfg.xml
</value>
</property>
</bean>
-----------
*不要忘记加载数据库的jar包
步骤:
先加人jar包,(这里采用的是手动:Spring(spring.jar,log4j.jarjakarta-commons/commons-logging.jar)--hibernante(hibernate3.jar,lib/*.jar,数据库驱动)--sturts(sturs的所有jar包)--数据库驱动的jar包(如果hibernate没有加的话));
【hiberante】关联的原码和配置文件分别是:hibernate-3.2.0.ga.zip;hibernante.cfg.xml;
【spring】关联的原码是:F:\书籍\王勇Spring\Spring相关资料\spring-framework-2.0\dist\spring-src.zip;applicationContext.xml;(注意spring关联的只能是springjar包中的spring文件才可以)
【struts】关联的原码是:F:\书籍\王勇struts\JSTL_BeanUtils_Struts相关资料\struts_install\struts-1.2.9-src.zip,struts-cfg.xml;
-------------------------------------------------------------------------14.spring的总结:Ioc就相当于工厂,我们可以通过Ioc拿到对象,叫控制反转。IoC有两种实现方式:依赖查找和依赖注入。Spring实现是依赖注入。
--------------------------------------------------------------------------
15.oracle数据库的driver:Class.forName("oracle.jdbc.driver.OracleDriver");
oracle数据库的URL:String url="jdbc:oracle:thin:@localhost:1521:orcl";//其中1521是oracle的端口号,orcl是连接的数据库名(如我自己建立的oracle数据库的名字是orcl)
oracle数据库要加的jar包是ojdbc14.jar(有两个)
-------------------------------------------
16.spring的配置文件applicationContext.xml文件中: <ref bean="mybean"/>和
<ref local="mybean"/> 的区别:
有多个spring的配置文件,mybean不在当前xml中用<ref bean="mybean"/>
mybean在当前xml中用<ref local="mybean"/>
这些都是我学习spring的时候随笔写下的一些笔记,现在共享出来,希望能对学习spring的朋友有一些帮助。有需要可以QQ找我 1336051675