整合ssh——spring容器

来源:互联网 发布:mysql分布式事务 编辑:程序博客网 时间:2024/06/06 23:52

spring

spring概述(重点)

         当代的企业级应用绝不可能是一个个的独立系统.一般都是部署在多个进行交互的应用,同时这些应用又都有可能与其他企业的相关应用连接,从而构建一个复杂的,跨越internet的分布式企业应用集群.

企业级应用不但有强大的功能,还要能满足未来业务需求的变化,易于升级和维护.

传统JavaEE 解决企业应用问题时的"重量级"架构体系,使它的开发效率,开发难度和实际的性能都令人失望.正在人们苦苦寻找解决办法时,Spring以一个救世主的形象出现在广大的java程序员面前.

Spring的组成模块和几个重要的概念

Spring Core是框架的最基础部分,提供IOC和依赖注入特性.

Spring DAO 提供了JDBC抽象层,简化JDBC编码,同时代码更健壮.

Spring ORM部分对Hibernate等OR映射框架提供了支持.

Spring AOP是基于Spring Core的符合规范的面向方面编程的实现,其重要组成部分是代理,必须理解它们,否则很难用好Spring AOP.

Spring Web是为Spring在Web应用程序中使用提供的支持

依赖注入(DI):  应用组件不应该负责查找资源或者其他依赖的协作对象。配置对象的工作应该由IoC容器负责

控制反转(IOC):它把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。

IOC容器:IOC容器就是具有依赖注入功能的容器,IOC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖

总结:依赖注入和控制反转可以理解为实现了同一作用就是,将程序之间的关系和数据转移给ioc容器管理,依赖注入和控制反转是框架的普遍都存在的特性。

Spring Corespring框架中最低层核心的模块。提供了最基本的Ioc思想框架。Spring采用工厂模式管理beans顶级接口是 BeanFactory

Spring配置实现(重点)

配置实现原理

         在web.xml文件中配置ContextLoaderListener,该类实现了ServletContextListener接口,配置此类后当web容器启动时收到事件回调,ContextLoaderListener的监听器方法,加载spring的配置文件同时创建了WebApplicationContext 对象。(此类为web的上下文对象服务)。

ApplicationContext接口

 接口实现类:ClassPathXmlApplicationContext     

通过以下方法可以读取配置信息。

 ApplicationContextcontext = new ClassPathXmlApplicationContext("bean.xml");

 接口实现类:WebApplicationContext

xml基本约束

         导入spring的jar包目录下的schema\beans\最新版本

         注解约束:导入schema\context 下的最新包

         导入包(新版本) : spring-aop-xxxx

 

基本配置信息

默认放在src下ApplicationContext.xml的配置

1、开启指定包下及其子包的注解:         <context:component-scanbase-package=""></context:component-scan>

2 Bean元素

                   id属性:给被管理的对象起个名字

                   name属性:是id属性的别名(可省略)

                   class属性:对象的完整类名

                   scope属性:处理对象创建方法(处理并发请求)

                            singleton(默认):单例对象,获取的对象为单例对象,构造方法只执行一次,( action对象建议不要配置为单例的,其它对象层可以采用默认的)。

                            prototype:标识后,每次获得后才创建,每次创建都是新的

                            request(了解):web环境下,对象与request生命周期一样

                            session(了解):与session生命周期一致

                    init-mathod 属性:(init-mathod ="方法名")配置一个方法(bean中的方法),作为生命周期初始化方法,创建时立即调用。

                   destory-mathod 属性:(destory-mathod="方法名")配置一个生命销毁方法

import元素:导入其它配置文件

         <importresource="classpath:lm.practice.spring.IHello"/>

注入方式(重点)

使用属性的setter方法注入

Setter方法注入,bean中要有依赖对象的set方法

<beanname="user" cass="" ></bean>

         <!--value属性注入:为user对象中名为name的属性注入tom值

         ref对象引用注入: user类含有car对象属性,将设置好的car的给到user-->

                   <prppertyname="name" value="tom"></prpperty>

                   <prppertyname="car" ref="car"></prpperty>

</bean>

<beanname="car" class="car">

                   <prppertyname="color" value="red"></prpperty>

                   <prppertyname="name" value="宾利"></prpperty>

</bean>

使用构造器注入

构造方法注入:bean中构造方法一个是无参的,一个是实例了依赖对象的构造方法

将上面的car对象注入到下面user对象,

         使用<constructor-arg>标签:

                   Name 属性:依赖属性名

                  Index:构造方法的参数顺序,

                  type:依赖对象类名

<beanname="user" class="">

          <constructor-argname="name" value="tom" index="0" type="java.lang.String"/>                    <constructor-arg name="car" value="car"  />

</bean>

p名称注入(了解)

         导入p名称空间

         <bean name="user"class="" p:name="tom"p:age="18"></bean>  //值注入

         <bean name="user"class="" p:name="tom" p:age="18" p:属性名-ref="bean对象" /> 

spel注入:(了解)

取其它bean的值为自己的值

                   <beanname="user1" class="">

                            <prppertyname="name" value="#{user.name}"></prpperty>

                            <prppertyname="car" ref="car"></prpperty>

                   </bean>

 

复杂类型注入(list、map)

<beanname="test" class="">

         <property name="list"value="tom"></property> //只有一个值可以按之前的注入

         <property name="list">

                   <list>    //向集合中注入多个值(数组,将list换成array)

                            <value>list1</value>

                            <value>list2</value>

                   </list>

         </property>

         <property name="map">

                   <map>    //向集合中注入多个值(数组,将list换成array)

                            <entrykey="" value=""></entry>

                            <entrykey="car" value-ref="car对象"></entry> //map中注入对象

                   </map>

         </property>

</bean>

        

Spring的日志       

为方便bean的实例化过程,spring采用log4j做日志输出,将log4j-1.2.15.jar添加到项目

控制日志输出log4j.properties文件内容如下:

#所有日志的根日志,修改该日志属性对所有日志起作用

log4j.rootLogger=info,console

#输出级别debug

log4j.logger.cn.jbit.facelook=DEBUG

#输出级别info

log4j.logger.com.opensymphony.xwork2=info

#输出源的输入位置是控制台

log4j.appender.console=org.apache.log4j.ConsoleAppender

#采用的布局类

log4j.appender.console.layout=org.apache.log4j.PatternLayout

log4j.appender.console.layout.ConversionPattern=%d%p [%c] - %m%n

Spring对象

         1、空参创建

                            ApplicationContextac = new

         2、 静态工厂

                            创建一个类,构造方法中创建对象

         3、实例工厂 

使用注解实例:在javabean中:

                   @Component("类名");

                   相等于: <bean name="user" class="com.test"  />

                   @Service    //servic层

                   @Controller  //web层

                   @Repository    //dao层

         作用范围:

                   设置作用域:@Scope(scopeName=)

                   赋值(在属性前或set方法前):@Value("tom")  //设置初始值

                   方法前:类@PreConstruct 初始化后调用

                            @Pre

STS插件

         1、手动安装插件

         2、安装好spring插件的eclipse

spring 和junit整合测试                 

         导入libs下的 test包   

         //会帮我们创建容器使用指定配置的文件

         测试方法前加入:@RunWith(SpringJUnit4ClassRunner.class)           

                  @ContextConfiguration("classpath:applicationContext.xml")      

                   @Resource(name="user")     

                   private User u;          //上面的注解直接创建对象

spring的aop编程(重点!!)

aop使用代理技术的原理

         使用代理技术对类的功能进行加强(使用aop思想,在方法执行前后加入增强的方法/加入配置信息,

         动态代理(优先):被代理对象要实现接口才能产生代理对象代理方法Proxy.newProxyInstance();

         cglib代理:可以对任何类生成代理,原理是对目标对象进行继承代理

                            如果目标对象被final修饰,则该类无法被cglib代理

名称解释

         Joinpoint (连接点):目标对象中可以增强的方法,

         Pointcut (切入点):目标对象连接点的集合(可以筛选要增强的方法)

         Advice (通知、增强):要增强的代码(代理的代码)

         Target(目标对象):被代理的对象

         Weaving (织入): 将通知应用到切入点的过程

         Proxy (代理) :将通知织入到目标对象后,形成代理对象

         aspect(切面)切入点 +通知,两名词相加                

spring实现aop的几种方法    

准备通知:前置通知--目标方法运行前调用

                            后置通知--目标方法运行后调用(异常后不调用)

                            环绕通知 -- 运行前后都调用

                            异常拦截通知--出现异常调用

                            后置通知--目标方法运行后调用(异常后也调用)

                   配置进行织入,织入目标对象:

一:编程式代理对象硬编码

         1、针对目标对象写一个实现类(切面),要实现代理接口MethodBeforeAdvice/afterxx,重写接口的方法,实现的接口直接决定了在目标对象前或后增强功能

         2、先配置目标对象 bean 和代理 bean

         3、配置 代理 bean  : class =ProxyFactoryBean

         <bean id="helloProxy"class="org.springframework.aop.framework.ProxyFactoryBean">

                   <!--目标对象实现的接口 -->

                   <propertyname="proxyInterfaces" value="com.robin.IHello" />

                   <!-- 目标对象的 bean -->

                   <propertyname="target" ref="helloSpeaker" />  

                   <!-- 配置通知的 bean -->

                   <property name="interceptorNames">

                            <list>

                                     <value>logBeforeAdvice</value>

                            </list>

                   </property>

         </bean>

.xml配置代理对象配置 

                   1、写通知类实现MethodInterceptor 接口重写invoke()方法(这个接口就诠释了动态代理的底层处理),注意要运用proceed()方法,执行目标对象方法

                   例如:

                   public class LogInterceptorimplements MethodInterceptor {

                            private Loggerlogger = Logger.getLogger(this.getClass().getName());

                       public Object invoke(MethodInvocation m)throws Throwable {

                                     logger.log(Level.INFO,"method starts..." + m.getMethod());

                                     Objectresult = null;

                                      try {

                                       result = m.proceed(); //  如果有多个interceptor

                                       //转给下一个interceptor来处理 如果没有执行目标对象的方法  再层层返回  interceptor栈

                                     } finally {

                                               logger.log(Level.INFO,"method ends..." + m.getMethod() + "\n");

                                     }

                                     returnresult;

                      }

                   }

                   2、配置通知和目标对象,配置 ProxyFactoryBean(同上)

                  

.xml配置无代理对象使用<aop>标签配置       

         1、写通知类 不需要实现接口,直接创建通知方法

                   void xbefore(JoinPointjointPoint)   //JoinPoint包含切面对象信息可以省略

         2、配置实现目标bean 通知bean(需要插入的方法类)

         3、只用<aop>标签配置xml

        <aop:config>

                  <!--引用advice通知 -->                 

                  <aop:aspectid="logging" ref="logBeforeAdvice">

                  <!--advice类型时机 -->

                  <!--pointcut切面属性设置 表达式匹配   *任何返回值类型符合

                    com.robin.IHello.*接口任意方法符合 (..)任何参数 -->

<!-- 例如:在目标对象前,任意返回值的IHello接口下的所有方法前插入,参数不限,插入的增强方法为xbefore-->         

                  <aop:beforepointcut="execution(* com.robin.IHello.*(..))"method="xbefore"/>

                 </aop:aspect>

        </aop:config>        

         将上面的aop配置换一种写法:

                   <aop:config>

                           <aop:pointcutexpression="execution(* com.robin.IHello.*(..))"id="pc"/>

                           <aop:aspectref="logBeforeAdvice" >

                  <!--指定通知类中的方法如何代理:指定名为before方法作为前置通知 -->

                           <aop:beforemethod="xbefore" pointcut-ref="pc" />

                           </aop:aspect>

                   </aop:config>       

四、使用注解配置 aop

                   1、  配置目标bean 以及 通知bean

                   2、开启注解配置aop <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

                   @Aspect //@Aspect说明该类是个切面

                   public class TestAspect {

                   //@Pointcut 定义一个切入点,对com.yyj.service包及子包下的所有方法

                  //方法无方法体,为方便同类中其他方法使用此处配置的切入点

                             @Pointcut("execution(*com.yyj.service.*.*(..))")

                             public void testPointCut(){

                             }

                            @Before("aspect()")                 //使用上面的切入点

                            public voidbefore(JoinPoint joinPoint){

                                               if(log.isInfoEnabled()){

                                                        log.info("before" + joinPoint);

                                               }

                            }                          

Spring配置aop的详细步骤:

         导包:(目前为止 spring有10个包: 4+2日志)

         + spring的aop包: aop和 aspects

                   +spring需要的第三方aop包: aopalliance   aspectj.xx

                   准备目标对象(需要增强的类如 userServic)

配置xml

                  配置目标对象:

                            <beanname="" class=""></>

                   配置通知对象:

                            <beanname="" class=""></>

                   配置将通知织入目标对象:

                   <!-- 1. 配置目标对象 -->

         <bean name="userService"class="cn.itcast.service.UserServiceImpl"  />

                   <!-- 2. 配置通知对象 MyAdvice为通知类! -->

                   <beanname="myAdvice" class="cn.itcast.d_springaop.MyAdvice"></bean>

                   <!-- 3. 配置将通知织入目标对象 -->

                   <aop:pointcutexpression="execution(* cn.itcast.service.*ServiceImpl.*(..))"id="pc"/>

                   <aop:aspectref="myAdvice" >

         <!--指定通知类中的方法如何代理:指定名为before方法作为前置通知 -->

                            <aop:before method="before"pointcut-ref="pc" />

                            <!-- 后置 -->

                            <aop:after-returningmethod="afterReturning" pointcut-ref="pc" />

                            <!-- 环绕通知 -->

                            <aop:aroundmethod="around" pointcut-ref="pc" />

                            <!-- 异常拦截通知 -->

                            <aop:after-throwingmethod="afterException" pointcut-ref="pc"/>

                            <!-- 后置 -->

                            <aop:aftermethod="after" pointcut-ref="pc"/>

                   </aop:aspect>

         </aop:config>

                                              

spring整合hibernate

配置获取SessionFactory

         1、在applicationContext.xml中导入hibernate.cfg.xml文件,获得sessionFactory

         2、使用SessionFactory 配置Dao层对象,

         <!-- 使用LocalSessionFactoryBean 可以导入很多形式的 hibernatede1配置信息-->

        <beanid="sessionFactory"class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

                  <propertyname="configLocation">

                           <value>classpath:hibernate.cfg.xml</value>

                  </property>

        </bean>  

         <!-- 2、配置DAO层,各种方法都需要使用sessionFactory完成curd操作,只有class不同 -->

         <bean id="userDao"class="com.juan.oa.dao.impl.UserDaoHibimpl" >       

                            <propertyname="sessionFactory" ref="sessionFactory" />

         </bean>

配置扩展

LocalSessionFactoryBean可以配置多种hibernate信息。例如:

         configLocation 属性加载hibernate配置文件创建sessionFactory 连接数据库

         mappingResources属性导入映射文件

         hibernateProperties属性设置hibernate属性

         dataSource属性注入数据源实现不同数据库切换

整合后Dao层的写法

方法一:直接配置使用hibernate的操作:

                   1、在Dao中定义sessionFactory对象属性,然后获得session完成cord操作

 

方法二:使用spring简化增删改操作:实现 HibernateDaoSupport接口

                   2、通过getHibernateTemplate()方法获得 HibernateTemplate在通过此类的方法进行简单的增删改查

         类似:JdbcTemplate /JpaJdbcTemplate /ConnectionCallback<T>/JpaDaoSupport /JdbcDaoSupport

                   例如:List list = getHibernateTemplate().findByExample(User);

方法三:使用spring简化查询操作:实现 HibernateDaoSupport接口

                   List lists =getHibernateTemplate().executeFind(new HibernateCallback() {

                            public ObjectdoInHibernate(Session session) throws HibernateException,  SQLException {

                                     String hql= "from  User where name=? and password=?";

                                     Query query= session.createQuery(hql);

                                     query.setParameter(0,user.getName());

                                     query.setParameter(1,user.getPassword());

                                     List list =query.list();

                                     returnlist;

                            }

                   });

结论

         1、spring提供了很多模板 整合Dao技术:      orm持久化技术有 jdbc  /shibernate3.0  / ibatis /jpa

         2、spring中 可以操作数据库的对象,该对象封装了jdbc的技术:

         JDBCTemplate => JDBC模板对象 与 dbutils的 QueryRunner 非常相似       

                   ComboPooledDataSourcedataSource = new ComboPooledDataSource();

                   dataSource.setDriverClass("com.mysql.jdbc.Driver");

                   dataSource.setJdbcUrl("jdbc:mysql:///hibernate_32");

                   dataSource.setUser("root");

                   dataSource.setPassword("1234");

                   //1 创建JDBC模板对象

                   JdbcTemplate jt = newJdbcTemplate();

                   jt.setDataSource(dataSource);

                   //2 书写sql,并执行

                  Stringsql = "insert into t_user values(null,'rose') ";

                  jt.update(sql);

hibernate的配置转移到spring

1、  导包:4+2、spring-test、spring-aop、junit4类库、c3p0连接池、JDBC驱动、spring-jdbc、spring-tx事务

         (配置读取properties文件)

         <!-- 指定spring读取db.properties配置数据库 -->

         <!-- 1.将连接池放入spring容器,获得数据源 -->

 

        <context:property-placeholderlocation="classpath:db.properties" />

        <beanname="dataSource"class="com.mchange.v2.c3p0.ComboPooledDataSource" >

                  <propertyname="jdbcUrl" value="${jdbc.jdbcUrl}"></property>  

                  <propertyname="driverClass" value="${jdbc.driverClass}" ></property>

                  <propertyname="user" value="${jdbc.user}" ></property>

                  <propertyname="password" value="${jdbc.password}"></property>

        </bean>

 

<!-- 2.将JDBCTemplate放入spring容器

         注意:如果没有配置jdbc模板对象,则不能使用此c3p0提供的模板操作

        可以直接使用数据源配置Dao层,Dao层实现 HibernateDaoSupport接口

        通过getHibernateTemplate().executeFind()方法,写hql语句,操作数据库

         -->

         <bean name="jdbcTemplate"class="org.springframework.jdbc.core.JdbcTemplate" >

                   <propertyname="dataSource" ref="dataSource" ></property>

         </bean>

<!-- 3.将UserDao放入spring容器 -->

         <bean name="userDao"class="cn.itcast.a_jdbctemplate.UserDaoImpl" >

                  <!--<property name="jt" ref="jdbcTemplate"></property> -->

                   <propertyname="dataSource" ref="dataSource" ></property>

         </bean>

spring封装的事务操作

         DriverManagerDataSource --> DataSourceTransactionManager-->

         1、spring封装了一个接口,用来应对不同平台操作事务的不同:       PlatformTransactionManager接口,

         实现类:DataSourceTransactionManager

         HibernateTransitionmanager (结合hibernate,用SessionFactory获取事务管理对象)

         注意:在spring中玩事务管理.最为核心的对象就是TransactionManager对象

         2、  spring事务的属性隔离级别:是否只读事务的传播行为(当多个方法应放在同一事务中时,使用propagation属性,="REQUIRED"时为存在事务则不再创建新事务。)

spring管理事务的三种方式

第一种:编程式

只通过配置获得DataSource,通过数据源获取事务管理

         切面程序:

         private DataSourceTransactionManagertransactionManager;//事务管理器

         private DefaultTransactionDefinitiondef;//用来设置事务特性

         private JdbcTemplate jdbcTemplate;

                  

         public void setDataSource(DriverManagerDataSourcedataSource) {

                            transactionManager=newDataSourceTransactionManager(dataSource);

                            jdbcTemplate=newJdbcTemplate(dataSource);

                            def=newDefaultTransactionDefinition();

                            //设置事务的特性

                  def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

                            //存在事务就使用,不存在创建新事务

                   }

                   TransactionStatustransactionStatus= transactionManager.getTransaction(def);

使用传统的jdbcc获取数据源配置:

         <bean id="dataSource"

                   class="org.springframework.jdbc.datasource.DriverManagerDataSource"><!-- 这里获得基本jdbc连接 -->

                   <propertyname="driverClassName"              value="com.mysql.jdbc.Driver"/>

                   <propertyname="url" value="jdbc:mysql://localhost:3306/test" />

                   <propertyname="username" value="root" />

                   <propertyname="password" value="123456" />

         </bean>

         <bean id="userDao"class="com.robin.UserDao">

                   <propertyname="dataSource" ref="dataSource" />

         </bean>

第二种:编程式:有代理对象的配置

         1、只需定义jdbcTemplate属性 通过setDataSource方法获取配置的数据源给jdbcTemplate赋值

                   private  JdbcTemplate  jdbcTemplate;

                   public void setDataSource(DataSource dataSource) {

                            jdbcTemplate = newJdbcTemplate(dataSource);

                   }

         <beanid="transactionManager" //定义事务管理器bean

         class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

        <propertyname="dataSource" ref="dataSource"/>

    </bean>

    <bean id="userDAO"  class="com.robin.UserDAO">

        <propertyname="dataSource" ref="dataSource"/>

    </bean>

    <bean id="userDAOProxy"  //定义userDao的代理对象

         class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">

        <propertyname="proxyInterfaces"> //提供接口信息给代理对象

            <list>

               <value>com.robin.IUserDAO</value> //连接点是接口的方法中

            </list>

        </property>

        <property name="target"ref="userDAO"/> //目标对象 真实对象

        <propertyname="transactionManager" ref="transactionManager"/> //引用事务管理器

        <propertyname="transactionAttributes"> //事务特性设置

        <props>

             <propkey="insert*">PROPAGATION_REQUIRED</prop> //传播行为                                        </props>

        </property>       

    </bean> 

第三种:无代理对象的xml配置

         先配置一个事务通知,在使用aop织入到目标方法

         <!--           isolation:隔离级别

                   propagation:传播行为

                   read-only:是否只读-->

<!--  定义的事务的advice 标签,时机:开始和结束,动作:针对insert* find* -->

         <tx:advice id="txAdvice"transaction-manager="transactionManager">

                   <tx:attributes>                  <!-- 定义事务属性 -->

                   <!-- 定义事务的语义   insert*开头的方法-->

                   <tx:methodname="insert*" propagation="REQUIRED"/>

                   <!-- 定义事务的语义  find*开头的方法 -->

                   <tx:methodname="find*" read-only="true"/>

         </tx:attributes>

</tx:advice>

<!-- 织入  -->

<aop:config>

         <!-- 切入点 包含连接点com.robin.IUserDAO包下所有方法,用advice增强处理 -->

         <aop:pointcutid="userDAOPointcut"             

                <!--配置切点表达式 -->

                 expression="execution(*com.juan.ssh.test2.UserDao.*(..))"/>

                 <!--将连接点和advice关联告诉被通知者advisor -->

        <aop:advisoradvice-ref="txAdvice" pointcut-ref="userDAOPointcut"/>

</aop:config>

第四种注解配置事务:(导入tx约束)

         1、 开启使用注解管理aop事务 transaction-manager:事务管理器要在之前配置它的bean。注意:proxy-target-class属性为true时,是类的代理,false接口的代理

         <tx:annotation-driven/>

         <tx:annotation-driventransaction-manager="transactionManager"proxy-target-class="false" />

         2、使用·注解 :在类前使用注解 @Transactional (注解的参数查资料),也可以在接口上使用         

         事物传播行为介绍:

         @Transactional(propagation=Propagation.REQUIRED)

         如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)

         事务隔离级别:

         @Transactional(isolation =Isolation.REPEATABLE_READ) 可重复读(会出现幻读)

jdbc结论:

         1、通过各种连接池或框架自带连接获取DataSource(数据源)

         2、使用DataSource获得sessionFactory(工厂)

         3、使用sessionFactory获取事务处理对象TransactionTemplate(事务模板)

         例如:

         TransactionTemplate transactionTemplate= new TransactionTemplate( new                                          HibernateTransactionManager(getSessionFactory()));

         4、如果在Spring的配置文件中引用hibernate.cfg.xml文件,那么要记住,hibernate的事务,默认自动提交是关闭的,

         这时在spring中配置事务就可能会失败。正确的做法是将hibernate的配置转移到spring中。

         5、注意,使用spring来管理事务要记住,默认只有运行错误才会回滚,而检查错误是不会回滚的。

    

 

 

原创粉丝点击