笔记——spring基本使用(控制反转IOC、面向切面编程AOP、声明式事务)

spring温习笔记


Spring是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。
Spring 的控制反转IOC、面向切面编程AOP等特性不多说。
本文核心内容:搭建一个Spring Demo
概要:想要启动spring这个大工厂,需要通过加载spring的核心配置文件类创建spring的核心类ApplicationContext,

ApplicationContext application = new ClassPathXmlApplicationContext("applicationContext.xml");这样spring就启动起来了。通过getBean方法可以手动获取Ban对象:

ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");

Student s=ac.getBean(Student.class);
这样可以看出使用spring之前需要先将spring的xml核心配置文件编辑好,这块的配置这里只做简单的配置使用,不进行深度研究。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-4.1.xsd">
           
           	<!--通过该标签可以导入其他的xml文件  这样就可以将配置进行分开管理  -->
           <import resource="aop.xml"/>	<!--将aop的配置放到了该xml文件中  -->
           <import resource="tx.xml"/>	<!--将关于事务的配置放到该xml文件中  -->
           <!-- 扫描Component组件  -->
           <context:component-scan base-package="com"/>
           <context:component-scan base-package="haha"/>
</beans>


关于控制反转IOC:将我们平时对对象的创建和管理交给spring这个大工厂,由他在我们需要的时候给我创建并注入给我们,
所以关于IOC的另一个说法就是D依赖注入,我们使用的对象需要依赖spring来注入到程序中,来做到集中管理,降低耦合的作用。
在使用这一特性时要让spring知道需要管理那些类和注入到哪里,平时常用注解的方式来配置,注解的方式感觉便捷很多,
在xml中开启组件扫描spring会自动扫描"com"包下的所有组件(Component、Controller、Service、Repository)
添加了注解的类会被spring管理,在需要使用的地方添加声明一个该对象的引用,在该属性上添加注入的注解(@Autowired、@Resource)两者之间的区别:

Autowired是自动注入,自动从spring的上下文找到合适的bean来注入
Resource用来指定名称注入
Qualifier和Autowired配合使用,指定bean的名称
Service,Controller,Repository分别标记类是Service层类,Controller层类,数据存储层的类,spring扫描注解配置时,会标记这些类要生成bean。
Component是一种泛指,标记类是组件,spring扫描注解配置时,会标记这些类要生成bean。
上面的Autowired和Resource是用来修饰字段,构造函数,或者设置方法,并做注入的。而Service,Controller,Repository,Component则是用来修饰类,标记这些类要生成bean。

import org.springframework.stereotype.Component;
@Component
public class TestComponentScan {


	private String tname="DingZuoHeng";


	public  TestComponentScan(){}
	//private  TestComponentScan(){}
	
	public String getTname() {
		return tname;
	}
	public void setTname(String tname) {
		this.tname = tname;
	}
	
}
该类为需要被spring管理的component组件。
import javax.annotation.Resource;
import org.springframework.stereotype.Component;
@Component
public class Student {
	@Resource
	TestComponentScan testComponentScan;
	public void haveClass(){
		System.out.println("Student类中的haveClass方法执行。。。"+testComponentScan.getTname());
	}
}


将上述组件注入到Student类中,启动spring并运行haveClass方法就可以看到控制台输出被注入类的信息。
以上就是spring IOC注解方式的简单使用。下面为AOP简单使用:


aop的相关术语:

    1 增强(Before、After、Around等)    要额外添加的功能/ 提取出来的重复功能(体现为一个方法)
    2 切面(Aspect)    组织增强的地方 放到代码里就是个类   
    3 连接点(pointcut)  可以添加增强的地方放 spring里就是方法 
    4 切入点  被添加了增强的连接点 
    5 织入    添加增强的过程
    6 目标    要添加增强的地方 

springAop的开发步骤 :

    1 导包  spring需要额外的aop支持 aspectJ 
    2 编写  切面代码
    3 编写  配置文件 或注解 

导入依赖后、编写切面以及增强、其实就是编写一个类然后在该类里面编写方法。
写好后可以直接在增强上添加注解(例如:@Before("execution(* com.*.Student.have*(..))")),或者在配置文件中
添加:
 
   <aop:aspectj-autoproxy/>  <-- 开启注解方式的Aspect  -->
  	<aop:config>
    	<aop:aspect  ref="aspect2" >
    			<aop:before method="testAspectbefore" pointcut="execution(void com.entity.*.*(..))"/>
    			<aop:after method="testAspectafter" pointcut="execution(void com.entity.*.*(..))"/>
    	</aop:aspect>
    </aop:config>  

切入点表达式

 execution ( 表达式 )
 表达式 :通配方法: * 代表所有返回值 类的全名一直到方法名(..) 代表所有参数 
 例:execution (* com.oracle.aop.Student.haveClass(..))
AOP的基本使用就到这里了。在这里在提一个必然会使用的spring声明式事务管理,它是基于AOP技术来实现了。
声明式事务:基于AOP实现(动态代理方式织入事务、提交/回滚事务),只需要要配置文件中配置好事务规则(tx及aop配置或使用@Transactional注解),注解方式开发简洁推荐使用。
 
   <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
        <property name="jdbcUrl" value="jdbc:mysql://localhost/test"/>
        <property name="user" value="root"/>
        <property name="password" value="123456"/>
        <property name="maxPoolSize" value="10"/>
        <property name="initialPoolSize" value="2"/>
    </bean>
在xml中配置一个bean,让spring的事务平台管理类加入到容器中,并提供数据源,这里以c3p0来演示。因使用注解的便利性
大多数时都是使用@Transactional注解 ,在使用该注解时需要在配置中添加如下:
<tx:annotation-driven transaction-manager="transactionManager"/>

来开启对事务注解


关于事务的其他需要了解的:

事务隔离级别(与数据库四个级别一致)

1> TransactionDefinition.ISOLATION_DEFAULT    # 这是默认值,表示使用底层数据库的默认隔离级别。大部分数据库通常默认是:READ_COMMITTED读已提交;
2> TransactionDefinition.ISOLATION_READ_UNCOMMITTED   # 一个事务可以读取另一个事务修改但还没有提交的数据。
     存在问题:该级别不能防止脏读,不可重复读和幻读,因此很少使用该隔离级别。比如PostgreSQL实际上并没有此级别。
3> TransactionDefinition.ISOLATION_READ_COMMITTED     # 一个事务只能读取另一个事务已经提交的数据。可以防止脏读,这也是大多数情况下的推荐值。
4> TransactionDefinition.ISOLATION_REPEATABLE_READ    # 一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。可以防止脏读和不可重复读。
5> TransactionDefinition.ISOLATION_SERIALIZABLE    # 所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,可以防止脏读、不可重复读以及幻读。
     但是这将严重影响程序的性能。通常情况下也不会用到该级别。


脏读(Dirty read):脏读发生在一个事务读取了被另一个事务改写但还未提交的数据时。如果这些改变在稍后被回滚,那么之前的事务读取的到数据就是无效的。
不可重复读(Nonrepeatable read):不可重复读发生在一个事务执行相同的查询两次或两次以上,但每一次的查询结果不同时。这通常是由于另一个并发的事务在两次查询之间更新了数据。
幻读(Phantom read):幻读是一个事务读取几行记录后,另一个事务插入了一些记录,幻读就发生了。在后来的查询中第一个事务就会发现有一些原来没有的额外的记录。

事务传播行为(TransactionDefinition)

1> PROPAGATION_MANDATORY # 该方法必须运行在一个事务中。如果当前事务不存在则抛出异常。
2> PROPAGATION_NESTED    # 如果当前存在一个事务,则该方法运行在一个嵌套的事务中。被嵌套的事务可以从当前事务中单独的提交和回滚。如果当前不存在事务,则开始一个新的事务。各厂商对这种传播行为的支持参差不齐,使用时需注意。 
3> PROPAGATION_NEVER     # 当前方法不应该运行在一个事务中。如果当前存在一个事务,则抛出异常。
4> PROPAGATION_NOT_SUPPORTED    # 当前方法不应该运行在一个事务中。如果一个事务正在运行,它将在该方法的运行期间挂起。
5> PROPAGATION_REQUIRED    # 该方法必须运行在一个事务中。如果一个事务正在运行,该方法将运行在这个事务中。否则,就开始一个新的事务。
6> PROPAGATION_REQUIRES_NEW    # 该方法必须运行在自己的事务中。它将启动一个新的事务。如果一个现有的事务正在运行,将在这个方法的运行期间挂起。
7> PROPAGATION_SUPPORTS    # 当前方法不需要事务处理环境,但如果一个事务已经在运行的话,这个方法也可以在这个事务里运行。

猜你喜欢

转载自blog.csdn.net/qq_32721817/article/details/79227868