光辉岁月

生命的快乐在于对世界上万事万物、对人世间悲欢离合的思考和感悟

Spring笔记

Spring笔记

Spring基础:属于一个应用型框架,轻量级框架,可以说是一个大杂会,是一个大型的工厂。

Spring核心类库:

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实现注入给我们

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

6、编写客户端

 

IOC容器:控制反转,控制反转给我们的spring容器去管理,以前是我们来控制的,是我们自己来new对象等。

DI:注入技术,依赖的注入(还有一种实现控制反转的技术实现叫依赖查找)

普通类型的注入配置:
<bean id="testBean" class="com.spring.dao.testBean">
  <property name="strValue" value="string"></property>
  <property name="intValue" value="1"></property>
  <property name="setValue">
    <set>
      <value>set1</value>
      <value>set2</value>
    </set>
  </property>
  <property name="listValue">
    <list>
      <value>list1</value>
      <value>list2></value>
    </list>
  </property>
  <property name="arrayValue">
    <list>
      <value>arry1</value>
      <value>arry2</value>
    </list>
  </property>
  <property name="mapValue">
    <map>
      <entry key="k1" value="v1"></entry>
      <entry key="k2" value="v2"></entry>
    </map>
  </property>
</bean>

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

    * 如何定义属性编辑器?
        * 继承PropertyEditorSupport类,覆写setAsText()方法,参见:UtilDatePropertyEditor.java
        * 将属性编辑器注册到spring中,参见:applicationContext-editor.xml

依赖对象的注入方式,可以采用:
    * ref属性
    * <ref>标签
    * 内部<bean>来定义

日期类型的注入:spring不识别日期类型,需要自己系一个属性编辑器来转换,继承类PropertyEditorSupport

例如:

public class UtilDatePropertyEditor extends PropertyEditorSupport {
private String format;

public String getFormat() {
return format;
}

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

@Override
public void setAsText(String text) throws IllegalArgumentException {
SimpleDateFormat sdf = new SimpleDateFormat(format);
try {
Date date = sdf.parse(text);
this.setValue(date);
} catch (ParseException e) {
e.printStackTrace();
}
}
}

<!--内部<bean>来定义-->
<bean id="CustomEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
    <property name="customEditors">
        <map>
            <entry key="java.util.Date">
                <bean class="com.spring.util.UtilDatePropertyEditor">
                    <property name="format" value="yyyy-MM-dd"/>
                </bean>
            </entry>
        </map>
    </property>
</bean>

<!-- 也可以如下的写法
<bean id="CustomEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
    <property name="customEditors">
        <map>
            <entry key="java.util.Date" value-ref="UtilDatePropertyEditor"/>
        </map>
    </property>
</bean>

<bean id="UtilDatePropertyEditor" class="com.spring.util.UtilDatePropertyEditor">
    <property name="format" value="yyyy-MM-dd"/>
</bean>
-->

如何将公共的注入定义描述出来?
    * 通过<bean>标签定义公共的属性,指定
abstract=true
    * 具有相同属性的类在<bean>标签中指定其
parent属性

    参见:applicationContext-other.xml

<!-- 公共属性的配置 -->
<bean id="BeanAbstruct" abstract="true">
    <property name="id" value="100"/>
    <property name="name" value="zhangshan"/>
</bean>

<!-- 使用parent属性来制定公共属性 -->
<bean id="bean3" parent="BeanAbstruct" class="com.spring.dao.Bean3">
    <!-- 也可以覆盖继承来的公共属性 -->
    <property name="name" value="lisi"/>
    <property name="pwd" value="123"></property>
</bean>
<bean id="bean4" parent="BeanAbstruct" class="com.spring.dao.Bean4"></bean>

 

Bean的作用域

当多次使用BeanFactory。getBean()的时候,当get同一个bean的时候,他们的应用时相等的(默认是相等的),但是可以改变:
<!-- bean id="testBean" scope="prototype" class="com.spring.dao.testBean" -->
<bean id="testBean" scope="singleton" class="com.spring.dao.testBean">
scope可以取值:
  * singleton:每次调用getBean的时候返回相同的实例
  * prototype:每次调用getBean的时候返回不同的实例

 

Spring的装配方式

*根据名称自动装配 default-autowire="byName"
*根据类型自动装配 default-autowire="byType"

 

AOP:提供了声明式服务。提供代理服务。

静态代理:

      比如对UserManager的安全性检查(UserManager的每个方法都要先进行安全检查),

代理类必须要与原类实现同样的接口,即有共同的接口,它的缺点是,代理类的每个方法都必须加一个安全性检查,安全性检查散步在代理类里了。

IOC管理对象,但是AOP不管对象,只管横切性的东西拿出来,在运行时加进去。

基于jdk的动态代理:

    基于静态代理的缺点,如我除了安全性检查,还想加一个日子呢,这样导致代理类的每个方法都要去更改了。

public class SecurityHandler implements InvocationHandler{

//目标对象
private Object targetObject;

//创建代理类
public Object newProxy(Object obj) {
   this.targetObject = obj;
   return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
            targetObject.getClass().getInterfaces(),
            this);
}

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
   checkSecurity();
   Object ret = null;
   try {
      ret = method.invoke(this.targetObject, args);
   } catch(Exception e) {
      e.printStackTrace();
   }
   return ret;
}

public void checkSecurity() {
System.out.println("checkSecurity()");
}
}

test:

public class Client {
   public static void main(String[]args) {
      SecurityHandler handler = new SecurityHandler();
      UserManager usermanager =(UserManager) handler.newProxy(new       UserManagerImpl());

      usermanager.addUser("zhu", "123");
   }
}

注意:也可以配置,当方法(Method)是delete的时候,才做安全性检查。method.getName()可以获取当前调用的方法名称。

横切性的问题,它会散步在代码的各个角落,如安全性检查,我们叫横切性关注点(Cross cutting concern),advice(横切点的实现)()Before Advice 、after advice,横切类(如刚刚的SecurityHandler类),JoinPoint(连接点,spring只支持方法的连接点),Weave(植入,把切面应用到目标对象上的这样的一个过程叫植入)

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定义切面

3、在Aspect定义Pointcut和Advice

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

<aop:aspectj-autoproxy/>

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

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

/**
* 定义Aspect
* @author Administrator
*
*/
@Aspect
public class SecurityHandler {

   /**
   * 定义Pointcut,Pointcut的名称就是allAddMethod,此方法不能有返回值和参数,该方法只是一个
   * 标识
   *
   * Pointcut的内容是一个表达式,描述那些对象的那些方法(订阅Joinpoint)
   */
   @Pointcut("execution(* add*(..)) || execution(* del*(..))")
   private void allAddMethod(){};

      /**
      * 定义Advice,标识在那个切入点何处织入此方法
      */
   @Before("allAddMethod()")
   private void checkSecurity() {
      System.out.println("----------checkSecurity()---------------");
   }

}

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、配置如下
<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的支持

Aspect默认情况下不用实现接口,但对于目标对象(UserManagerImpl.java),在默认情况下必须实现接口
如果没有实现接口必须引入CGLIB库

我们可以通过Advice中添加一个JoinPoint参数,这个值会由spring自动传入,从JoinPoint中可以取得
参数值、方法名等等

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、声明式事务配置
* 配置SessionFactory
* 配置事务管理器
* 事务的传播特性
* 那些类那些方法使用事务

2、编写业务逻辑方法
* 继承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。


原理:在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());

需要配置listener及参数:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:applicationContext-*.xml</param-value>
</context-param>

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

3、通过BeanFactory取得业务对象,调用业务逻辑方法

 

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将业务逻辑对象注入过来

3、在struts-config.xml文件中配置Action
  * <action>标签中的type属性需要修改为org.springframework.web.struts.DelegatingActionProxy
DelegatingActionProxy是一个Action,主要作用是取得BeanFactory,然后根据<action>中的path属性值
到IoC容器中取得本次请求对应的Action

4、在spring配置文件中需要定义struts的Action,如:
<bean name="/login" class="com.bjsxt.usermgr.actions.LoginAction" scope="prototype">
<property name="userManager" ref="userManager"/>
</bean>
  * 必须使用name属性,name属性值必须和struts-config.xml文件中<action>标签的path属性值一致
  * 必须注入业务逻辑对象
  * 建议将scope设置为prototype,这样就避免了struts Action的线程安全问题

Struts + Spring + Hibernate集成

基本配置:ApplicationContext-common.xml:

<!--配置Hibernate的SessionFactory-->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
   <property name="configLocation">classpath:hibernate.hcf.xml</property>
</bean>

<!--配置事物管理器-->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTranscationManager">
   <property name="sessionFactory">
        <ref bean="sessionFactory"/>
   </property>
</bean>

<!-- 配置事务的传播特性 -->
<tx:advice id="txAdvice" transcation-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(* xxx.xxx.*.*(..))"/>
     <aop:advisor pointcut-ref="allManagerMethod" advice-ref="txAdvice"/>
</aop:config>

在web.xml中加入相应的配置:

配置spring的bean配置文件
<context-param>
     <param-name>contextConfigLocation</param-name>
     <param-value>classpath*:applicationContext-*.xml</param-value>
</context-param>

配置LoaderListern:
<listener>
     <listener-class>
          org.springframework.web.context.ContextLoaderListener
     </listener-class>
</listener>

配置spring提供的字符转换filter:
<filter>
     <filter-name>springCharacterEncoding</filter-name>
     <filter-class>
          org.springframework.web.filter.CharacterEncodingFilter
     </filter-class>
     <init-param>
          <param-name>encoding</param-name>
          <param-value>utf-8</param-value>
     </init-param>
</filter>
<filter-mapping>
     <filter-name>springCharacterEncoding</filter-name>
     <url-pattern>/*</url-pattern>
</filter-mapping>


阅读更多
个人分类: java
想对作者说点什么? 我来说一句

spring笔记

2018年04月12日 726KB 下载

SPRING 笔记SPRING 笔记

2010年03月05日 94KB 下载

Spring笔记和小结

2010年07月28日 46KB 下载

spring MVC笔记

2018年04月12日 757KB 下载

spring注解笔记

2017年10月20日 378KB 下载

spring笔记整合在一起的

2009年08月28日 218KB 下载

spring入门笔记源码

2010年08月22日 139KB 下载

spring 学习资料

2011年10月08日 47KB 下载

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭