Spring框架详解

1、Spring框架

概述:spring框架可以解决对象创建以及对象之间依赖关系的一中框架。

常用专业术语:

  • 组建/框架设计:
侵入式设计:引入了框架后对现有的结构产生影响,即需要继承或实现某些特定类。例如:struts框架

非侵入式设计:引入了框架对现有的结构无影响。例如:hibernate、spring框架。

  • 控制反转(inversion on control----IOC)
控制反转(IOC):对象的创建交给外部容器创建。

依赖注入(DI):处理对象的依赖关系

区别:

控制反转解决对象的创建问题。而依赖注入是在对象创建成功后解决对象的关系的处理。

  • AOP面向切面编程
面向切面编程:切面---可以简单的理解为一个类,由很多重复代码组成的类。如:事务、日志等。

2、Spring IOC容器(applicationContext.xml)

IOC容器是spring核心,作用:创建对象和处理对象的依赖关系

默认的applicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
<span style="white-space:pre">	</span>	
<span style="white-space:pre">	</span>
</beans>


2.1 对象创建的细节

a、什么时候创建

scope="prototype"(默认值)   在用到对象的时候才创建-------------多例(action对象)

scope="singleton"   在启动(容器初始化之前),就已经创建了对象,整个web应用只有一个-------------------单例(dao、service、工具类)

b、是否延迟创建

lazy-init="false"(默认值) 不延迟创建,即在启动的时候就创建。

lazy-init="true" 延迟初始化,在用到对象的时候才创建。

2.2 创建对象的几种方式

a、调用无参构造器

b、带参构造器

c、工厂类创建:静态/动态

<!-- ###############对象创建############### -->
	
	<!-- 1. 默认无参数构造器 
	<bean id="user1" class="cn.User"></bean>
	-->
	
	<!-- 2. 带参数构造器 -->
	<bean id="user2" class="cn.User">
		<constructor-arg index="0" type="int" value="100"></constructor-arg>
		<constructor-arg index="1" type="java.lang.String" value="Jack"></constructor-arg>
	</bean>
	
	<!-- 定义一个字符串,值是"Jack" ;  String s = new String("jack")-->
	<bean id="str" class="java.lang.String">
		<constructor-arg value="Jacks"></constructor-arg>
	</bean>
	<bean id="user3" class="cn.User">
		<constructor-arg index="0" type="int" value="100"></constructor-arg>
		<constructor-arg index="1" type="java.lang.String" ref="str"></constructor-arg>
	</bean>
	
	
	<!-- 3. 工厂类创建对象 -->
	<!-- # 3.1 工厂类,实例方法 -->
	<!-- 先创建工厂 -->
	<bean id="factory" class="cn.ObjectFactory"></bean>
	<!-- 在创建user对象,用factory方的实例方法 -->
	<bean id="user4" factory-bean="factory" factory-method="getInstance"></bean>
	
	
	<!-- # 3.2 工厂类: 静态方法 -->
	<!-- 
		class 指定的就是工厂类型
		factory-method  一定是工厂里面的“静态方法”
	 -->
	<bean id="user" class="cn.ObjectFactory" factory-method="getStaticInstance"></bean>

2.3 对象依赖关系

spring中常用的几种注入方式

a、通过构造器

b、通过set方法给属性注入值(最常用)

*****************************
需要给set方法。
*****************************
<!-- dao instance -->
	<bean id="userDao" class="cn.dao.UserDao"></bean>

	<!-- service instance -->
	<bean id="userService" class="cn.service.UserService">
		<property name="userDao" ref="userDao"></property>
	</bean>
	
	<!-- action instance -->
	<bean id="userAction" class="cn.action.UserAction">
		<property name="userService" ref="userService"></property>
	</bean>

c、p名称空间

 <span style="white-space:pre">	</span><bean id="userDao" class="cn.dao.UserDao"></bean>
	 
	 <bean id="userService" class="cn.service.UserService" p:userDao-ref="userDao"></bean>
	 
	 <bean id="userAction" class="cn.action.UserAction" p:userService-ref="userService"></bean>
<p align="left"><span style="color:teal;"><span style="white-space:pre">	</span><</span><span style="color: rgb(63, 127, 127);">bean</span> <span style="color: rgb(127, 0, 127);">id</span>=<em><span style="color:#2A00FF;">"user"</span></em><span style="color: rgb(127, 0, 127);">class</span>=<em><span style="color:#2A00FF;">"cn.entity.User"</span></em> <span style="color: rgb(127, 0, 127);">p:name</span>=<em><span style="color:#2A00FF;">"Jack0001"</span></em><span style="color: teal;">></</span><span style="color: rgb(63, 127, 127);">bean</span><span style="color: teal;">></span></p>

d、注解

注解方式可以简化spring的IOC容器的配置。。但不利于后期的维护。

使用步骤:

1)先引入context名称空间

                    xmlns:context="http://www.springframework.org/schema/context"

          2)开启注解扫描

                    <context:component-scanbase-package="包"></context:component-scan>

          3)使用注解

通过注解的方式,把对象加入ioc容器。   创建对象以及处理对象依赖关系,相关的注解:

                     @Component   指定把一个对象加入IOC容器

@Repository   作用同@Component; 在持久层使用

@Service      作用同@Component; 在业务逻辑层使用

@Controller    作用同@Component; 在控制层使用

@Resource     属性注入

3、AOP编程

3.1 概述:

aop(aspectobject programming  面向切面编程)功能:让关注点代码和业务代码分离

关注点:重复代码

切面:关注点形成的类就叫切面类。

面向切面编程就是对重复代码进行抽取,在业务执行的时候再动态植入。

切入点:

可以通过切入点表达式拦截指定的类的指定方法,在类或方法执行的时候动态植入切面类代码。

3.2 注解方式实现AOP编程

步骤

1) 先引入aop相关jar文件           (aspectj  aop优秀组件)                                      

         spring-aop-3.2.5.RELEASE.jar   【spring3.2源码】

aopalliance.jar                              【spring2.5源码/lib/aopalliance】

aspectjweaver.jar                         spring2.5源码/lib/aspectj】或【aspectj-1.8.2\lib

aspectjrt.jar                                   spring2.5源码/lib/aspectj】或【aspectj-1.8.2\lib

注意:用到spring2.5版本的jar文件,如果用jdk1.7可能会有问题。

                   需要升级aspectj组件,即使用aspectj-1.8.2版本中提供jar文件提供。

2) bean.xml中引入aop名称空间

3) 开启aop注解

4) 使用注解

@Aspect                                                              指定一个类为切面类             

@Pointcut("execution(* cn.itcast.e_aop_anno.*.*(..))")  指定切入点表达式

@Before("pointCut_()")                                   前置通知: 目标方法之前执行

@After("pointCut_()")                                      后置通知:目标方法之后执行(始终执行)

@AfterReturning("pointCut_()")              返回后通知: 执行方法结束前执行(异常不执行)

@AfterThrowing("pointCut_()")                    异常通知:  出现异常时候执行

@Around("pointCut_()")                                  环绕通知: 环绕目标方法执行

3.3 XML实现AOP编程

Xml实现aop编程:

         1) 引入jar文件  【aop 相关jar, 4个】

         2) 引入aop名称空间

         3)aop 配置

                   *配置切面类 (重复执行代码形成的类)

                   *aop配置:  拦截哪些方法 / 拦截到方法后应用通知代码

	<!-- dao 实例 -->
	<bean id="userDao" class="cn.dao.UserDao"></bean>
	<bean id="orderDao" class="cn.dao.OrderDao"></bean>
	
	<!-- 切面类 -->
	<bean id="aop" class="cn.aop.Aop"></bean>
	
	<!-- Aop配置 -->
	<aop:config>
		<!-- 定义一个切入点表达式: 拦截哪些方法 -->
		<aop:pointcut expression="execution(* cn.*.*.*(..))" id="pt"/>
		<!-- 切面 -->
		<aop:aspect ref="aop">
			<!-- 环绕通知 -->
			<aop:around method="around" pointcut-ref="pt"/>
			<!-- 前置通知: 在目标方法调用前执行 -->
			<aop:before method="begin" pointcut-ref="pt"/>
			<!-- 后置通知: -->
			<aop:after method="after" pointcut-ref="pt"/>
			<!-- 返回后通知 -->
			<aop:after-returning method="afterReturning" pointcut-ref="pt"/>
			<!-- 异常通知 -->
			<aop:after-throwing method="afterThrowing" pointcut-ref="pt"/>
			
		</aop:aspect>
	</aop:config>

3.4 切入点表达式

切入点表达式:  可以对指定的“方法”进行拦截;  从而给指定的方法所在的类生层代理对象。

 

<aop:config>
		
		<!-- 定义一个切入点表达式: 拦截哪些方法 -->
		<!--<aop:pointcut expression="execution(* cn.*.*(..))" id="pt"/>-->
		
		<!-- 【拦截所有public方法】 -->
		<!--<aop:pointcut expression="execution(public * *(..))" id="pt"/>-->
		
		<!-- 【拦截所有save开头的方法 】 -->
		<!--<aop:pointcut expression="execution(* save*(..))" id="pt"/>-->
		
		<!-- 【拦截指定类的指定方法, 拦截时候一定要定位到方法】 -->
		<!--<aop:pointcut expression="execution(public * cn.g_pointcut.OrderDao.save(..))" id="pt"/>-->
		
		<!-- 【拦截指定类的所有方法】 -->
		<!--<aop:pointcut expression="execution(* cn.g_pointcut.UserDao.*(..))" id="pt"/>-->
		
		<!-- 【拦截指定包,以及其自包下所有类的所有方法】 -->
		<!--<aop:pointcut expression="execution(* cn..*.*(..))" id="pt"/>-->
		
		<!-- 【多个表达式】 -->
		<!--<aop:pointcut expression="execution(* cn.g_pointcut.UserDao.save()) || execution(* cn.g_pointcut.OrderDao.save())" id="pt"/>-->
		<!--<aop:pointcut expression="execution(* cn.g_pointcut.UserDao.save()) or execution(* cn..g_pointcut.OrderDao.save())" id="pt"/>-->
		<!-- 下面2个且关系的,没有意义 -->
		<!--<aop:pointcut expression="execution(* cn.g_pointcut.UserDao.save()) && execution(* cn.g_pointcut.OrderDao.save())" id="pt"/>-->
		<!--<aop:pointcut expression="execution(* cn.g_pointcut.UserDao.save()) and execution(* cn.g_pointcut.OrderDao.save())" id="pt"/>-->
		
		<!-- 【取非值】 -->
		<!--<aop:pointcut expression="!execution(* cn.g_pointcut.OrderDao.save())" id="pt"/>-->
		<aop:pointcut expression=" not execution(* cn.g_pointcut.OrderDao.save())" id="pt"/>
		
		<!-- 切面 -->
		<aop:aspect ref="aop">
			<!-- 环绕通知 -->
			<aop:around method="around" pointcut-ref="pt"/>
		</aop:aspect>
	</aop:config>

4、事务

事务是一组操作的执行单元,相对于数据库操作来讲,事务管理的是一组SQL指令,比如增加,修改,删除等,事务的一致性,要求,这个事务内的操作必须全部执

行成功,如果在此过程种出现了差错,比如有一条SQL语句没有执行成功,那么这一组操作都将全部回滚

事务特性(ACID)

Atomic(原子性):要么都成功,要么都失败

Consistent(一致性):数据应该不被破坏

Isolate(隔离性):用户间操作不相混淆

Durable(持久性):永久保存


4.1 事务控制概述

编程式事务控制

         自己手动控制事务,就叫做编程式事务控制。

         Jdbc代码:   Conn.setAutoCommite(false);  // 设置手动控制事务

         Hibernate代码:  Session.beginTransaction();    // 开启一个事务

         【细粒度的事务控制:可以对指定的方法、指定的方法的某几行添加事务控制】

         (比较灵活,但开发起来比较繁琐:每次都要开启、提交、回滚.)

声明式事务控制

         Spring提供了对事务的管理, 这个就叫声明式事务管理。

         Spring提供了对事务控制的实现。用户如果想用Spring的声明式事务管理,只需要在配置文件中配置即可;不想使用时直接移除配置。这个

实现了对事务控制的最大程度的解耦。

         Spring声明式事务管理,核心实现就是基于Aop。

         【粗粒度的事务控制:只能给整个方法应用事务,不可以对方法的某几行应用事务。】

         (因为aop拦截的是方法。)

         Spring声明式事务管理器类:

                   Jdbc技术:DataSourceTransactionManager

                   Hibernate技术:HibernateTransactionManager

4.2 声明式事务管理

步骤:

         1) 引入spring-aop相关的4个jar文件

         2) 引入aop名称空间  【XML配置方式需要引入】

         3) 引入tx名称空间    【事务方式必须引入】

xml实现:

<!--  数据源对象: C3P0连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass"value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl"value="jdbc:mysql:///hib_demo"></property>
        <property name="user"value="root"></property>
        <property name="password"value="root"></property>
        <property name="initialPoolSize"value="3"></property>
        <property name="maxPoolSize"value="10"></property>
        <property name="maxStatements"value="100"></property>
        <property name="acquireIncrement"value="2"></property>
    </bean>
 
<span style="white-space:pre">	</span><!--  配置事务管理器类 -->
	<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!-- 配置事务增强(如果管理事务?) -->
	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
			<tx:method name="get*" read-only="true"/>
			<tx:method name="find*" read-only="true"/>
			<tx:method name="*" read-only="false"/>
		</tx:attributes>
	</tx:advice>
	
	<!--  Aop配置: 拦截哪些方法(切入点表表达式) + 应用上面的事务增强配置 -->
	<aop:config>
		<aop:pointcut expression="execution(* cn.itcast.a_tx.DeptService.*())" id="pt"/>
		<aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/>
	</aop:config>

注解方式实现:

使用注解实现Spring的声明式事务管理,更加简单!

步骤:

         1) 必须引入Aop相关的jar文件

         2) bean.xml中指定注解方式实现声明式事务管理以及应用的事务管理器类

         3)在需要添加事务控制的地方,写上: @Transactional

@Transactional注解:

         1)应用事务的注解

         2)定义到方法上: 当前方法应用spring的声明式事务

         3)定义到类上:   当前类的所有的方法都应用Spring声明式事务管理;

         4)定义到父类上: 当执行父类的方法时候应用事务。

	<!-- 数据源对象: C3P0连接池 -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
		<property name="jdbcUrl" value="jdbc:mysql:///hib_demo"></property>
		<property name="user" value="root"></property>
		<property name="password" value="root"></property>
		<property name="initialPoolSize" value="3"></property>
		<property name="maxPoolSize" value="10"></property>
		<property name="maxStatements" value="100"></property>
		<property name="acquireIncrement" value="2"></property>
	</bean>

	<!-- 事务管理器类 -->
	<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!-- 开启注解扫描 -->
	<context:component-scan base-package="包"></context:component-scan>
	
	<!-- 注解方式实现事务: 指定注解方式实现事务 -->
	<tx:annotation-driven transaction-manager="txManager"/>


事务属性:

@Transactional(
			readOnly = false,  // 读写事务
			timeout = -1,       // 事务的超时时间不限制
			noRollbackFor = ArithmeticException.class,  // 遇到数学异常不回滚
			isolation = Isolation.DEFAULT,              // 事务的隔离级别,数据库的默认
			propagation = Propagation.REQUIRED			// 事务的传播行为
	)
	public void save(Dept dept){
		deptDao.save(dept);
		int i = 1/0;
		deptDao.save(dept);
	}

事务传播行为:

         Propagation.REQUIRED

                   指定当前的方法必须在事务的环境下执行;

                   如果当前运行的方法,已经存在事务, 就会加入当前的事务;

         Propagation.REQUIRED_NEW

                   指定当前的方法必须在事务的环境下执行;

                   如果当前运行的方法,已经存在事务:  事务会挂起; 会始终开启一个新的事务,执行完后;  刚才挂起的事务才继续运行。
























  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值