Spring核心技术

1、Spring框架

  • Spring Core spring的核心功能: IOC容器, 解决对象创建及依赖关系
  • Spring Web Spring对web模块的支持, spring mvc模式
  • Spring DAO Spring 对jdbc操作的支持 【JdbcTemplate模板工具类】
  • Spring ORM spring对orm的支持:可以与mybatis整合
  • Spring AOP 切面编程

2、spring是单例还是多例

  • singleton 作用域
    当把 一个bean定义设置为singleton作用域时,Spring IOC容器只会创建该bean定义的唯一实例。这个单一实例会被存储到单例缓存(singleton cache)中,并且所有针对该bean的后续请求和引用都 将返回被缓存的对象实例。
  • Prototype
    prototype作用域部署的bean,每一次请求(将其注入到另一个bean中,或者以程序的方式调用容器的 getBean()方法)都会产生一个新的bean实例,相当与一个new的操作,对于prototype作用域的bean,有一点非常重要,那就是Spring不能对一个prototype bean的整个生命周期负责,容器在初始化、配置、装饰或者是装配完一个prototype实例后,将它交给客户端,随后就对该prototype实例不闻不问了。
  • request
    request表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效,配置实例:request、session、global session使用的时候首先要在初始化web的web.xml中做如下配置:
  • session
    session作用域表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效

3、SpringIOC 容器

容器创建对象
1) 调用无参数构造器
2) 带参数构造器
3) 工厂创建对象
工厂类,静态方法创建对象
工厂类,非静态方法创建对象

给对象的属性赋值

  1. 通过构造函数
  2. 通过set方法给属性注入值
  3. p名称空间
  4. 注解

@Resource与@Autowired区别

1、@Autowired与@Resource都可以用来装配bean. 都可以写在字段上,或写在setter方法上。
2、@Autowired默认按类型装配(这个注解是属业spring的),默认情况下必须要求依赖对象必须存在,如果要允许null 值,可以设置它的required属性为false,如:@Autowired(required=false) ,如果我们想使用名称装配可以结合@Qualifier注解进行使用,
3、@Resource(这个注解属于J2EE的),默认安照名称进行装配,名称可以通过name属性进行指定, 如果没有指定name属性,当注解写在字段上时,默认取字段名进行按照名称查找,如果注解写在setter方法上默认取属性名进行装配。 当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配

4、AOP编程

主要的功能是:日志记录,性能统计,安全控制,事务处理,异常处理等等。
主要的意图是:将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改 变这些行为的时候不影响业务逻辑的代码。

@Aspect							指定一个类为切面类		
@Pointcut("execution(* com.itmayiedu.service.UserService.add(..))")  指定切入点表达式

@Before("pointCut_()")				前置通知: 目标方法之前执行
@After("pointCut_()")					后置通知:目标方法之后执行(始终执行)
@AfterReturning("pointCut_()")		    返回后通知: 执行方法结束前执行(异常不执行)
@AfterThrowing("pointCut_()")			异常通知:  出现异常时候执行
@Around("pointCut_()")				环绕通知: 环绕目标方法执行

动态代理

1、JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口。如果想代理没有实现接口的类,就可以使用CGLIB实现。
2、CGLIB是一个强大的高性能的代码生成包,它可以在运行期扩展Java类与实现Java接口。它广泛的被许多AOP的框架使用,例如Spring AOP和dynaop,为他们提供方法的interception(拦截)。
3、 CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。

5、spring事务

事务应该在Service层统一控制。

1、Spring 事务的核心接口

Spring 通过一个名为spring-tx-4.3.6-RELEASE 的JAR包来管理事务,在这个JAR包中的org.Springframework.transaction 包中包含了三个接口文件:

  • PlatformTramsactionManager 主要用于管理事务,包括获取事务的状态、提交事务和回滚事务;
  • TramsactionDefinition 该接口是事务定义的对象,包括了获取事务的名称、隔离级别、事务的传播行为、超时时间、事务是否只读等;
  • TramsactionStatus 该接口是事务的状态,描述了某一个时间点事务状态信息,包括刷新事务、获取是否存在保存点、是否是新事务、是否回滚、设置事务回滚。
2、事务管理方式有2种

一种是传统的编程序事务管理,即通过代码来管理事务的开始、执行和异常以及回滚,一种是声明式管理,即通过配置文件的方式,原理是通过AOP技术实现,我们在实际开发过程中推荐使用声明式事务管理,效率会大大提升,因为只需要通过配置即可。

2.1 编程式事务控制

自己手动控制事务,就叫做编程式事务控制。
Jdbc代码:Conn.setAutoCommite(false); // 设置手动控制事务
Mybatis代码:Session.beginTransaction(); // 开启一个事务
细粒度的事务控制: 可以对指定的方法、指定的方法的某几行添加事务控制
(比较灵活,但开发起来比较繁琐: 每次都要开启、提交、回滚.)

public class UserDao {
	@Autowired
	private JdbcTemplate jdbcTemplate;
	public void add(String name, Integer age) {
		String sql = "INSERT INTO users(NAME, age) VALUES(?,?);";
		int update = jdbcTemplate.update(sql, name, age);
		System.out.println("updateResult:" + update);
	}
}

@Service
public class UserService {
	@Autowired
	private UserDao userDao;
	public void add() {
		userDao.add("lisi", 18);
		int i=1/0;//可能会发生异常
		userDao.add("link", 19);
	}
}

public class UserTest {
	public static void main(String[] args) {
		ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
		UserService userService = (UserService) applicationContext.getBean("userService");
		userService.add();
	}
}
@Component
public class TransactionUtils {
	// 事物管理器
	@Autowired
	private DataSourceTransactionManager dataSourceTransactionManager;
	public TransactionStatus begin() {
		TransactionStatus transaction = dataSourceTransactionManager.getTransaction(new DefaultTransactionDefinition());
		return transaction;
	}
	public void commit(TransactionStatus transaction) {
		dataSourceTransactionManager.commit(transaction);
	}
	public void rollback(TransactionStatus transaction) {
		dataSourceTransactionManager.rollback(transaction);
	}
}
  • bean.xml (Spring务管理配置)
<!-- 1. 数据源对象: 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://localhost:3306/test"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>

<!-- 2. JdbcTemplate工具类实例 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>

<!-- 配置事物 -->
<bean  id="DataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
@Aspect
@Component
public class Aop {

	@Autowired
	private TransactionUtils transactionUtils;

	private TransactionStatus begin;

	@Before("execution(* com.link.service.UserService.add(..))")
	public void bean(){
		System.out.println("......前置通知......");
	}

	@After("bean")
	public void commit(){
		System.out.println(".......后置通知......");
	}

	@AfterReturning("bean")
	public void afterRun(){
		System.out.println(".......运行通知......");
	}

	@AfterThrowing("bean")
	public void afterThrowing(){
		System.out.println(".......异常通知......");
		transactionUtils.rollback(begin);
	}

	@Around("bean")
	public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
		begin = transactionUtils.begin();
		System.out.println("我是环绕通知-前");
		// 放行实际方法
		proceedingJoinPoint.proceed();
		System.out.println("我是环绕通知-后");
		transactionUtils.commit(begin);
	}
}
2.2 声明式事务控制

Spring提供了对事务的管理, 这个就叫声明式事务管理。
Spring提供了对事务控制的实现。用户如果想用Spring的声明式事务管理,只需要在配置文件中配置即可;不想使用时直接移除配置。这个实现了对事务控制的最大程度的解耦。
Spring声明式事务管理,核心实现就是基于Aop。
粗粒度的事务控制: 只能给整个方法应用事务,不可以对方法的某几行应用事务。
(因为aop拦截的是方法。)

xml方式

<!-- 1. 数据源对象: 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://localhost:3306/test"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>

<!-- 2. JdbcTemplate工具类实例 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>

<!-- 配置事物 -->
<bean id="dataSourceTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>

<!—配置事物增强-->
<tx:advice id="txAdvice" transaction-manager="dataSourceTransactionManager">
	<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(* com.link.service.*.*(..))"
id="pt" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt" />
</aop:config>

注解方式

@Transactional
	public void add() {
		try {
			userDao.add("lisi", 18);
			int i = 1 / 0;
			userDao.add("yushengjun", 19);
		} catch (Exception e) {	TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
		}	
	}
3、事务特性

在这里插入图片描述

3.1 传播七种行为

Propagation(key属性确定代理应该给哪个方法增加事务行为。这样的属性最重要的部份是传播行为。)有以下选项可供使用:
• PROPAGATION_REQUIRED–支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
• PROPAGATION_SUPPORTS–支持当前事务,如果当前没有事务,就以非事务方式执行。
• PROPAGATION_MANDATORY–支持当前事务,如果当前没有事务,就抛出异常。
• PROPAGATION_REQUIRES_NEW–新建事务,如果当前存在事务,把当前事务挂起。
• PROPAGATION_NOT_SUPPORTED–以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
• PROPAGATION_NEVER–以非事务方式执行,如果当前存在事务,则抛出异常。

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

事务传播行为:
Propagation.REQUIRED
指定当前的方法必须在事务的环境下执行;
如果当前运行的方法,已经存在事务, 就会加入当前的事务;
Propagation.REQUIRED_NEW
指定当前的方法必须在事务的环境下执行;
如果当前运行的方法,已经存在事务: 事务会挂起; 会始终开启一个新的事务,执行完后; 刚才挂起的事务才继续运行。

public enum Propagation {
    REQUIRED(0),//表示当前方法必须运行在一个事务环境中,如果存在就直接使用,否则开启一个新的事务执行该方法
    SUPPORTS(1),//如果当前方法处于事务环境中则使用,否则不使用事务
    MANDATORY(2),//表示该方法的线程必须在事务中否则抛出异常
    REQUIRES_NEW(3), //要求在新事务中执行,如果已经在事务中了则先暂停然后启动新事务执行,如果不在则启动一个新事务后执行
    NOT_SUPPORTED(4), //不支持当前事务,总是以非事务状态执行,如果调用该方法的线程处于事务中泽先暂停然后执行
    NEVER(5), //不支持当前执行的方法在事务中,如果在抛出异常
    NESTED(6); //即便当前执行的方法在事务中也会启动一个新事务,然后执行该方法

    private final int value;
}

@Transactional 只能应用到 public 方法才有效
这是因为在使用 Spring AOP 代理时,Spring 在调用 TransactionInterceptor 在目标方法执行前后进行拦截之前,DynamicAdvisedInterceptor(CglibAopProxy 的内部类)的的 intercept 方法或 JdkDynamicAopProxy 的 invoke 方法会间接调用 AbstractFallbackTransactionAttributeSource(Spring 通过这个类获取 @Transactional 注解的事务属性配置属性信息)的 computeTransactionAttribute 方法

3.2 隔离级别
public enum Isolation {
    DEFAULT(-1),
    READ_UNCOMMITTED(1),
    READ_COMMITTED(2),
    REPEATABLE_READ(4),
    SERIALIZABLE(8);

    private final int value;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值