目录
注:本文是学习笔记,仅针对个人学习记录(只记录本人觉得重要或需要掌握的知识点)
2.1: IOC(Inversion of Control):反转控制
2.2: DI(Dependency Injection):依赖注入
注:本文是学习笔记,仅针对个人学习记录(只记录本人觉得重要或需要掌握的知识点)
第1章 Spring概述
- Spring是一个IOC(DI)和AOP容器框架。
-
Spring是一个容器,因为它包含并且管理应用对象的生命周期
第2章 IOC容器和bean配置
//1.创建IOC容器对象
ApplicationContext iocContainer =
new ClassPathXmlApplicationContext("helloworld.xml"); //构造函数中是spring的配置文件
//2.根据id值获取bean实例对象
Student student = (Student) iocContainer.getBean("student");
//3.打印bean
System.out.println(student);
2.1: IOC(Inversion of Control):反转控制
说白了就是以前的对象需要我们手动创建,现在只需要从spring容器中获取。
2.2: DI(Dependency Injection):依赖注入
组件以一种预先设置好的方式(例如set方法)接受来自容器的注入。
DI是IOC的实现,DI是具体实现,IOC是思想
2.3: ApplicationContext的主要实现类
ClassPathXmlApplicationContext:对应类路径下的实现类
FileSystemXmlApplicationContext:对应系统文件下的实现类
Spring默认是单例模式 可以在配置文件中指定多例模式
<bean id="hi" class="com.test.Hi" scope="singleton">
tips:<![CDATA[]]>内容在xml文件中将全部视为字符串
实际开发中几乎用不到Spring的主动bean 此处略
2.4 bean的生命周期
1.Spring IOC容器对bean的生命周期进行管理的过程:
① 通过构造器或工厂方法创建bean实例
② 为bean的属性设置值和对其他bean的引用
③ 调用bean的初始化方法
④ bean可以使用了
⑤ 当容器关闭时,调用bean的销毁方法
在配置bean时,通过init-method和destroy-method 属性为bean指定初始化和销毁方法
2.bean的后置处理器
bean后置处理器允许在调用初始化方法前后对bean进行额外的处理,废话不多说上代码
package com.xzcl.spring.beans.cysle;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;public class MyBeanProcessor implements BeanPostProcessor { //实现接口
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("postProcessAfterInitialization:" +beanName+","+arg1);
return bean;
}@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("postProcessBeforeInitialization: "+beanName+","+beanName);
return bean;
}// 方法一前一后 参数是对象和对象名称 注意最后在方法中把对象返回
}
2.4 bean的生命周期
使用外部属性文件
1.创建配置文件
prop.userName=root
prop.password=root
prop.url=jdbc:mysql:///test
prop.driverClass=com.mysql.jdbc.Driver
2.配置属性文件位置
<context:property-placeholder location="classpath:jdbc.properties"/>
3.直接使用
<!-- 从properties属性文件中引入属性值 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${prop.userName}"/>
<property name="password" value="${prop.password}"/>
<property name="jdbcUrl" value="${prop.url}"/>
<property name="driverClass" value="${prop.driverClass}"/>
</bean>
2.5 组件扫描
<context:component-scan base-package="包名"/>
如果仅希望扫描特定的类而非基包下的所有类,可使用resource-pattern属性过滤特定的类,示例
<context:component-scan base-package="包名" resource-pattern="类.class"/>
第3章 AOP
3.1 AOP术语
横切关注点 : 从每个方法中抽取出来的同一类非核心业务
切面(Aspect) : 封装横切关注点信息的类,每个关注点体现为一个通知方法
通知(Advice) : 切面要完成的具体工作 (原方法)
目标(Target) :被通知的对象(原方法)
代理(Proxy) 像目标对象应用通知之后的对象
连接点(Joinpoint) :可以具体融合的方法
切入点 :具体融合的方法
3.2 AOP实现
切面只是一个带有@Aspect注解的Java类,它往往要包含很多通知。
AspectJ支持5种类型的通知注解:
① @Before:前置通知,在方法执行之前执行
② @After:后置通知,在方法执行之后执行 (后置通知不管有没有异常都会执行)
@After("execution(* com.yl.spring.aop.impl.*.*(..))",returning="result") //配置切入点表达式
public void afterMethod(JoinPoint joinPoint,Object result) { //JP对象可以获得具体方法的名称
String methodName = joinPoint.getSignature().getName();
List<Object> args = Arrays.asList(joinPoint.getArgs());
System.out.println("The method " + methodName + " 的返回值是 " + result);
}
③ @AfterRunning:返回通知,在方法返回结果之后执行
@AfterRunning("execution(* com.yl.spring.aop.impl.*.*(..))") //配置切入点表达式
public void afterMethod(JoinPoint joinPoint) { //JP对象可以获得具体方法的名称
String methodName = joinPoint.getSignature().getName();
List<Object> args = Arrays.asList(joinPoint.getArgs());
System.out.println("The method " + methodName + " end with " + args);
}
④ @AfterThrowing:异常通知,在方法抛出异常之后执行
@AfterThrowing("execution(* com.yl.spring.aop.impl.*.*(..))",throwing="ex")
public void afterMethod(JoinPoint joinPoint,Exception ex) {
String methodName = joinPoint.getSignature().getName();
List<Object> args = Arrays.asList(joinPoint.getArgs());
System.out.println("The method " + methodName + "异常是 " + ex);
}
⑥ @Around:环绕通知,围绕着方法执行
@Around("execution(public int com.yl.spring.aop.ArithmeticCalculator.*(..))")
public Object aroundMethod(ProceedingJoinPoint pjd) {
pjp.proceeed(); //这个方法就是目标方法
}
切面优先级
@Aspect
@order(0)
public class 切面一{
}
@Aspect
@order(1)
public class 切面一{
}// @order中的数字越小优先级越高
动态代理的实现和底层原理另起一章讲
链接: [link](https://mp.csdn.net).
第4章 声明式事务 (此为Spring最核心的一章)
4.1实现简单的事务
(1)配置
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/> <!-- 需要数据源-->
</bean>
<!-- 启用事务注解 如果事务管理器的id是"transactionManager" 那么以下 transaction-manager 可以省略-->
<tx:annotation-driven transaction-manager="transactionManager"/>
(2).在需要进行事务控制的方法或者类上加注解 @Transactional
@Transactional //对当前类中所有的方法都起作用
@Service
public class BookShopServiceImpl implements BookShopService {
//只对当前的方法起作用
@Transactional
public void buyBook() {
4.2事务的属性细节
1. 事务的传播行为 propagation: 一个事务方法被另外一个事务方法调用时,当前的事务如何使用事务.
Propagation.REQUIRED 默认值. 使用调用者的事务.
Propagation.REQUIRES_NEW 将调用者的事务挂起, 重新开启事务来使用.
总结:其实就是大事务调用小事务的时候是否遵循大事务 默认为大 REQUIRES_NEW 为小
2.事务的隔离级别 isolation Isolation.以下
事务隔离级别 | 脏读 | 不可重复读 | 幻读 |
读未提交 read-uncommitted |
有 | 有 | 有 |
读已提交 read-committed |
无 | 有 | 有 |
可重复读 repeatable-read |
无 | 无 | 有 |
串行化 serializable |
无 | 无 | 无 |
另起文章专门说事务 连接:
3.事务的回滚与不回滚 可以通过设置 指定什么异常回滚 什么异常不回滚
rollbackFor 指定哪些异常回滚(声明异常类)
rollbackForClassName 指定哪些异常回滚(字符串)
noRollbackFor 指定哪些异常不回滚(声明异常类)
noRollbackForClassName 指定哪些异常不回滚(字符串)
@Transactional(rollbackFor=Exception.class)
@Transactional(rollbackFor="java.lang.Exception")
4.. 事务的只读设置:readOnly
true: 只读 代表着只会对数据库进行读取操作, 不会有修改的操作.(数据库会优化引擎,增加效率)
false: 非只读 不仅会读取数据还会有修改操作。
注:设置只读只是告诉事务我不进行操作 但是真正还是可以操作的 事务不会判断是否操作 所以设置了只读一定不要进行操作
5.事务的超时设置
timeout 不建议手动设置
总结:
Spring其实只做了两件事 一是配置beans 维护者beans的生命周期,二是根据AOP动态代理实现声明式事务。
在维护beans中 运用依赖注入实现控制反转的思想,从spring容器池中获取相应的bean并给属性赋值。
在声明式事务中运用面向切面技术,通过对目标方法的切入,获得代理对象,从而实现事务。