Spring学习笔记

来源:互联网 发布:决战紫禁之巅 知乎 编辑:程序博客网 时间:2024/06/06 06:42

(1)       applicationContext.xml中,打<括号没有办法跳出提示,在windows——>preference——>xml catalog中添加key type采用URI文件选择如图所示的xsd标签key中填写http://www.springframework.org/schema/beans/spring-beans-2.0.xsd

(2)spring依赖库

    * SPRING_HOME/dist/spring.jar

    * SPRING_HOME/lib/jakarta-commons/commons-logging.jar

    * SPRING_HOME/lib/log4j/log4j-1.2.14.jar

(3)spring Ioc容器的关键点:

    * 必须将被管理的对象定义到spring配置文件中

    * 必须定义构造函数或setter方法,让spring将对象注入过来

被依赖的配置bean id class

依赖的 bean

如果用构造方法注入:

配置方法:在UserManagerImpl中写入构造函数,

public UserManagerImpl(UserDao userDao) {

this.userDao = userDao;

}

在配置文件中写:

<bean id="userManager" class="com.bjsxt.spring.manager.UserManagerImpl">

          <constructor-arg ref="userDao4OracleImpl"/>

</bean>

setter方法注入:在UserManagerImpl中写入setter方法:

public void setUserDao(UserDao userDao) {

          this.userDao = userDao;

}

在配置文件中写:

<bean id="userManager" class="com.bjsxt.spring.manager.UserManagerImpl">

           <property name="userDao" ref="userDao4OracleImpl"/>

</bean>

4)编写客户端不用new方式取得userManager,用工厂模式取如下:

         BeanFactory factory =new ClassPathXmlApplicationContext("applicationContext.xml");//读取配置文件

                   UserManager userManager = (UserManager)factory.getBean("userManager");//取哪个bean

                   userManager.save("张三", "123");

注意点:没有侵入性,把spring扔掉也没有关系,用new也可以调用方法执行。但是struts就不行,把actionform去掉就不能编译。变化的业务层方向。

单例和工厂类都不要使用

不依赖于容器

5)注入:

bean赋值,在配置文件中赋值。给各种类型的数据赋值。

         <property name="strValue" value="Hello"/>

                   <!--

                   <property name="intValue" value="123"/>

                    -->

                    <property name="intValue">

                           <value>123</value>

                    </property>

                    <property name="listValue">

                           <list>

                                    <value>list1</value>

                                    <value>list2</value>

                           </list>

                    </property>

                    <property name="setValue">

                           <set>

                                    <value>set1</value>

                                    <value>set2</value>

                           </set>

                    </property>

                    <property name="arrayValue">

                           <list>

                                    <value>array1</value>

                                    <value>array2</value>

                           </list>

                    </property>

                    <property name="mapValue">

                           <map>

                                    <entry key="k1" value="v1"/>

                                    <entry key="k2" value="v2"/>

                           </map>

                    </property>

                    <property name="dateValue">

                           <value>2008-08-15</value>

                    </property>

取得bean的方法:

private BeanFactory factory;//是线程安全的只要设一个

        

         @Override

         protected void setUp()throws Exception {

                   factory =new ClassPathXmlApplicationContext("applicationContext-*.xml");    

         }

 

方法中调用这个就可以了:

Bean1 bean1 = (Bean1)factory.getBean("bean1");

配置文件中配置的东西都是字符串,要写属性转换器,就如date类型就要转换。

属性编辑器:类继承于:java.beans.PropertyEditorSupport

 

什么是属性编辑器,作用?

         * 自定义属性编辑器,spring配置文件中的字符串转换成相应的对象进行注入

         spring已经有内置的属性编辑器,我们可以根据需求自己定义属性编辑器

        

         * 如何定义属性编辑器?

                   * 继承PropertyEditorSupport类,覆写setAsText()方法,参见:UtilDatePropertyEditor.java

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

 

package com.bjsxt.spring;

 

import java.beans.PropertyEditorSupport;

import java.text.ParseException;

import java.text.SimpleDateFormat;

import java.util.Date;

 

/**

 * java.util.Date属性编辑器

 * @author Administrator

 *

 */

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;

         }

 

}

 

  <!-- 定义属性编辑器 -->     

         <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>  

 

 

依赖对象的注入方式,可以采用:

         * ref属性 <property name="bean3" ref="bean3"/>

         * <ref>标签<property name="bean4">

                            <ref bean="bean4"/>

                   </property>    

         * 内部<bean>来定义<bean class="com.bjsxt.spring.UtilDatePropertyEditor">

                                                        <property name="format" value="yyyy-MM-dd"/>

                                               </bean>

如何将公共的注入定义描述出来?

         * 通过<bean>标签定义公共的属性,指定abstract=true

         * 具有相同属性的类在<bean>标签中指定其parent属性

<bean id="beanAbstract" abstract="true">

               <property name="id" value="1000"/>

               <property name="name" value="Jack"/>

   </bean>        

  

   <bean id="bean3" class="com.bjsxt.spring.Bean3" parent="beanAbstract">

               <property name="name" value="Tom"/>//若不同重新赋值

               <property name="password" value="123"/>

   </bean> 

 

 

spring Bean的作用域:

scope可以取值: 

         * singleton:每次调用getBean的时候返回相同的实例

         * prototype:每次调用getBean的时候返回不同的实例 线程安全

方法(看创建几个实例):  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");

                   }

          

AOP:实现了声明式服务,使用JDK的动态代理实现的。

代理模式:可以控制原对象,不改变原对象的接口,静态代理类是确实能看到的,动态代理类是运行过程中生成的。

动态代理:实现接口InvocationHandler

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;

 

public class SecurityHandlerimplements InvocationHandler {

 

         private Object targetObject;

        

         public Object newProxy(Object targetObject) {//生成新到代理对象

                  this.targetObject = targetObject;

                  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();

                           throw new java.lang.RuntimeException(e);

                   }

                  return ret;

         }

 

         private void checkSecurity() {

                   System.out.println("----------checkSecurity()---------------");

         }

        

}

 

Cross cutting concern横切线的关注点,模块化的类叫Aspect(切面类 SecurityHandler例如上类的)类中横切线的关注点的实现方法叫advice(如上例中checkSecurity,分为before adviceafter advice等等),权限过滤条件pointcutadd*)所有以add开头的方法都要进行安全检查(before advice),把advice用到目标对象上的过程叫Weave(置入),连接点(joinpoint)就是使用切面类的方法,targetObject真实实现的对象,Proxy代理对象(Spring Aop)使用的是动态代理类。introduction:动态地加方法。

 

 

 

 

采用编程式事务(直接使用hibernate编程)

 

1getCurrentSession()openSession()的区别?

         * 采用getCurrentSession()创建的session会绑定到当前线程中,而采用openSession()

           创建的session则不会

         * 采用getCurrentSession()创建的sessioncommitrollback时会自动关闭,而采用openSession()

           创建的session必须手动关闭

session = HibernateUtils.getSessionFactory().getCurrentSession();

          

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>     

 

springhibernate的结合,使用声明式事务处理

、了解事务的几种传播特性

         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 属性执行

 

Spring事务的隔离级别

         1.      ISOLATION_DEFAULT:这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.

              另外四个与JDBC的隔离级别相对应

         2.      ISOLATION_READ_UNCOMMITTED:这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据。

              这种隔离级别会产生脏读,不可重复读和幻像读。

         3.      ISOLATION_READ_COMMITTED:保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据

         4.      ISOLATION_REPEATABLE_READ:这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。

              它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)

         5.      ISOLATION_SERIALIZABLE这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。

              除了防止脏读,不可重复读外,还避免了幻像读。

 

 

1、声明式事务配置

         * 配置SessionFactory

         * 配置事务管理器

         * 事务的传播特性

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

<?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">

         <!-- 配置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:config>

</beans>

 

 

 

2、编写业务逻辑方法

         * 继承HibernateDaoSupport类,使用HibernateTemplate来持久化,HibernateTemplate Hibernate Session的轻量级封装

public class UserManagerImplextends HibernateDaoSupport

this.getHibernateTemplate//取得session

         * 默认情况下运行期异常才会回滚(包括继承了RuntimeException子类),普通异常是不会滚的

         * 编写业务逻辑方法时,最好将异常一直向上抛出,在表示层(struts)处理

         * 关于事务边界的设置,通常设置到业务层,不要添加到Dao     

原创粉丝点击