| Spring是什么 | 轻量级 非侵入 | IOC  反转控制 把创建管理对象的权限交给spring AOP  ⾯向切⾯编程 对方法、接口级别的拦截器,解耦
 | 
| Spring快速⼊⻔ |  | 1. 在pom.xml中导⼊Spring开发的基本包坐标 spring-context 2. 编写Dao接⼝和实现类
 3. 在resources中创建Spring核⼼配置⽂件 applicationContext.xml
 4. 把Dao交给Spring的Bean进⾏管理  依赖注入(又叫DI)   ①set方法注入  ②构造方法注入
 5. 使⽤Spring的API获得Dao的Bean实例
 | 
| 常用属性 | <Bean>标签 id属性:在容器中Bean实例的唯⼀标识,不允许重复
 class属性:要实例化的Bean的全限定名
 scope属性:Bean的作⽤范围,常⽤是Singleton(默认)和prototype
 <property>标签:set方法注入,属性注⼊
 name属性:setXxx()方法的Xxx,属性名称
 value属性:注⼊的普通属性值
 ref属性:注⼊的对象引⽤值
 <list>标签
 <map>标签
 <properties>标签
 <constructor-arg>标签
 <import>标签:导⼊其他的Spring的分⽂件
 resource:引入其他文件的路径
 | 加载外部jdbc.properties <context:property-placeholder location="classpath:jdbc.properties"/>
 | 
| 重点API | ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); getBean("id")
 getBean(Class)
 |  | 
| Spring原始注解 |  | [注解]             [说明] @Component         使用在类上用于实例化Bean
 @Controller        使用在web层类上用于实例化Bean
 @Service           使用在service层类上用于实例化Bean
 @Repository        使用在dao层类上用于实例化Bean
 @Autowired         使用在字段上用于根据类型依赖注入,如果只使用@Autowired,就只按种类选择
 @Qualifier         结合@Autowired一起使用用于根据名称 id 进行依赖注入
 @Resource          相当于@Autowired+@Qualifier,按照名 id 称进行注入
 @Value             注入普通属性
 @Scope             标注Bean的作用范围
 @PostConstruct     使用在方法上标注该方法是Bean的初始化方法
 @PreDestroy        使用在方法上标注该方法是Bean的销毁方法
 
 [注解的组件扫描] - 一般扫描除controller层之外的
 <context:component-scan base-package="com.itheima"></context:component-scan>
 | 
| Spring新注解 |  | [注解]             [说明] @Configuration     用于指定当前类是一个 Spring 配置类,当创建容器时会从该类上加载注解
 @ComponentScan     用于指定 Spring 在初始化容器时要扫描的包。 作用和在 Spring 的 xml 配置文件中的 <context:component-scan base-package="com.itheima"/>一样
 @Bean              使用在方法上,标注将该方法的返回值存储到 Spring 容器中
 @PropertySource    用于加载.properties 文件中的配置
 @Import            用于导入其他配置类
 | 
| Spring整合Junit |  | ① 在pom.xml导入spring集成Junit的坐标 spring-context spring-test junit ② 自己新建一个测试类,类名上面使用 @Runwith(SpringJUnit4ClassRunner.class) 注解替换原来的运行期
 ③ 类名上面使用 @ContextConfiguration("classpath:applicationContext.xml") 或 @ContextConfiguration(classes = {被@Configuration指定配置类的类名.class})指定配置文件或配置类
 ④ 成员变量上面使用 @Autowired 注入需要测试的对象
 ⑤ 创建测试方法,上面使用 @Test 进行测试
 | 
| AOP 相关概念 | 底层:反射 
 [两种动态代理技术]
 JDK 代理   : 基于接口的动态代理技术
 cglib 代理 : 基于父类的动态代理技术
 
 [相关术语]
 Target(目标对象):代理的目标对象
 Proxy (代理):一个类被 AOP 织入增强后,就产生一个结果代理类
 Joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点
 · Pointcut(切入点):所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义
 · Advice(通知/ 增强):所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知
 · Aspect(切面):是切入点和通知(引介)的结合
 · Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程。spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入
 
 [切点表达式]
 execution( [修饰符]  返回值类型  包名.类名.方法名(参数) )
 例如:
 execution(public void com.itheima.aop.Target.method())
 execution(void com.itheima.aop.Target.*(..))
 execution(* com.itheima.aop.*.*(..))    // 重点掌握这种
 execution(* com.itheima.aop..*.*(..))
 execution(* *..*.*(..))
 
 [环绕增强方法]
 public Object around(ProceedingJoinPoint pjp) throws Throwable {
 System.out.println("环绕前置增强...");
 Object proceed = pjp.proceed();
 System.out.println("环绕后置增强...");
 return proceed;
 }
 | 【JDK动态代理(手写)】 Target target = new Target(); //创建目标对象
 //创建代理对象
 TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(target.getClass()
 .getClassLoader(),target.getClass().getInterfaces(),new InvocationHandler() {
 @Override
 public Object invoke(Object proxy, Method method, Object[] args)
 throws Throwable {
 System.out.println("前置增强代码...");
 Object invoke = method.invoke(target, args);
 System.out.println("后置增强代码...");
 return invoke;
 }
 }
 );
 proxy.method();
 
 【cglib动态代理(手写)】
 Target target = new Target(); //创建目标对象
 Enhancer enhancer = new Enhancer();   //创建增强器
 enhancer.setSuperclass(Target.class); //设置父类
 enhancer.setCallback(new MethodInterceptor() { //设置回调
 @Override
 public Object intercept(Object o, Method method, Object[] objects,
 MethodProxy methodProxy) throws Throwable {
 System.out.println("前置代码增强....");
 Object invoke = method.invoke(target, objects);
 System.out.println("后置代码增强....");
 return invoke;
 }
 });
 Target proxy = (Target) enhancer.create(); //创建代理对象
 proxy.method();
 | 
| AOP-XML | <aop:通知类型 method=“切面类中方法名” pointcut=“切点表达式"></aop:通知类型> [通知标签类型]
 前置通知        aop:before
 后置通知        aop:after-returning
 环绕通知        aop:around
 异常抛出通知    aop:after-throwing
 最终通知        aop:after
 
 [XML切点表达式的抽取]
 <aop:pointcut id="myPointcut" expression="execution(* com.itheima.aop.*.*(..))"/>
 <aop:before method="before" pointcut-ref="myPointcut"></aop:before>
 | 【使用步骤】 ① 在pom.xml导入 AOP 相关坐标  spring-context   aspectjweaver
 
 ② 创建目标接口和目标类(内部有切点)
 
 ③ 创建切面类(内部有增强方法)
 
 ④ 导入aop命名空间
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:aop="http://www.springframework.org/schema/aop"
 导入aop约束路径
 http://www.springframework.org/schema/context
 http://www.springframework.org/schema/context/spring-context.xsd
 http://www.springframework.org/schema/aop
 http://www.springframework.org/schema/aop/spring-aop.xsd
 
 ⑤ 在 applicationContext.xml 中
 使用标签 <bean> 将目标类和切面类的对象创建权交给 spring
 使用标签 <aop> 配置织入关系
 
 ⑥ 测试代码(Spring整合Junit)
 | 
| AOP-注解 | [通知注解类型] 前置通知        @Before
 后置通知        @AfterReturning
 环绕通知        @Around                 // 注意 配置环绕通知时,spring-context 与 aspectjweaver 1.8.4以下版本一起使用会引发jar包冲突
 异常抛出通知    @AfterThrowing
 最终通知        @After
 
 [注解切点表达式的抽取]
 @Pointcut("execution(* com.itheima.aop.*.*(..))")  // 注意 若想使用@Pointcut注解,aspectjweaver最低版本是1.8.9
 public void myPoint(){};
 
 @Before("MyAspect.myPoint()")
 public void before(){
 System.out.println("前置代码增强.....");
 }
 | 【使用步骤】 ① 在pom.xml导入 AOP 相关坐标  spring-context   aspectjweaver
 
 ② 创建目标接口和目标类(内部有切点)
 
 ③ 创建切面类(内部有增强方法)
 
 ④ 导入aop命名空间
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:aop="http://www.springframework.org/schema/aop"
 导入aop约束路径
 http://www.springframework.org/schema/context
 http://www.springframework.org/schema/context/spring-context.xsd
 http://www.springframework.org/schema/aop
 http://www.springframework.org/schema/aop/spring-aop.xsd
 
 ⑤ 使用注解 @Component 将目标类和切面类的对象创建权交给 spring
 使用注解 @Aspect 标注切面类
 使用通知注解 如 @Before 等标注通知方法
 
 在 applicationContext.xml 中
 配置注解扫描的组件扫描
 <context:component-scan base-package="com.itheima"></context:component-scan>
 配置aop自动代理
 <aop:aspectj-autoproxy/>
 
 ⑥ 测试代码(Spring整合Junit)
 | 
| JdbcTemplate | tx:事务 JdbcTemplate自动提交事务
 | 【使用步骤】 ① 在pom.xml导入 AOP 相关坐标  spring-jdbc  spring-tx
 
 ② 创建数据库表与实体类
 
 ③ 创建jdbc.properties配置文件
 
 ④ 用Spring管理并创建JdbcTemplate对象
 
 ⑤ 执行数据库操作(增删改查)
 | 
| 事务控制-XML | [4种隔离级别] 1. ISOLATION_READ_UNCOMMITTED:这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。
 2. ISOLATION_READ_COMMITTED:保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据
 3. ISOLATION_REPEATABLE_READ:这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。
 4. ISOLATION_SERIALIZABLE:这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。
 
 
 脏读(针对未提交的事务):即事务A读到了事务B还没有提交的数据。如果事务A对数据进行了更新,但是事务A并没有提交,但是事务B这个时候看到了事务A没有提交的更新。当事务A进行了回滚,那么刚刚事务B看到的数据就是脏数据。也就是脏读。
 例子:A 给 B 转了100万,但是 A 还没有提交,此时 B 查询自己账户,多了100万。然后 A 发现转错人了,回滚了事物。然后 B 100万就没了。在这个过程中 B 查到了没有提交的数据(多出的100万),这就是脏读。
 
 不可重复读(在一个事务里面读取了两次某数据,读出来的数据不一致,针对修改操作):即同一事务在事务执行过程中对同一个数据进行了多次读取,但是每一次读取的数据结果都不相同。原因是在两次读取间隔,数据别其他人修改了,导致了统一事务两次读取结果不一致。
 例子:A 查询银行余额为100万,B 这个时候取走了50万,此时余额变成了50万,A 再一次查询余额,变成了50万。对 A 而言两次结果不一致就是不可重复读。
 
 幻读(在一个事务里面的操作中发现了为被操作的数据,针对增删操作):即在事务 A多次读取数据集的过程中中,事务 B 对数据进行了新增操作或者删除操作,导致事务 A多次读取的数据集不一致。
 例子:A 修改当前公司所有职员信息的时候,B 向其中插入了一个新的职员,这个时候A 提交的时候发现了一个自己没有修改过的职员的信息,对 A 而言就像是产生了幻觉。
 
 [7种传播行为]
 1. REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。一般的选择(默认值)
 2. SUPPORTS:如果有事务,就会使用事务,如果没有,就不使用事务的方式执行。
 3. MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常
 4. REQUERS_NEW:每次都会新建事务它与REQUIRED的区别在于事务的回滚程度,调用B时,即使A有事务,B也会自己开启一个事务,那么这样就是存在两个不同的事务,如果B已经提交事务,A发生异常会进行回滚,那么B也是不会回滚的,若B发生异常,A进行捕获B的异常后,B进行回滚,A可以正常提交事务并执行
 5. NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
 6. NEVER:以非事务方式运行,如果当前存在事务,抛出异常
 7. NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行REQUIRED 类似的操作
 
 [超时时间]:设置调用此方法的最大时间,超出则强行中断,不在进行查询
 
 [是否只读]:声明此事务方法中只能做查询
 | 【使用步骤】 ① 在pom.xml导入 AOP 相关坐标  spring-context  aspectjweaver  spring-jdbc  spring-tx  spring-test  c3p0  mysql-connector-java  junit
 ② 创建实体和对应数据库
 ③ 创建持久层
 ④ 创建业务层
 ⑤ 配置applicationContext.xml
 ⑥ 创建Controller层并测试
 | 
| 事务控制-注解 |  | 【使用步骤】 ① dao层
 ② service层配置注解事务
 ③ 配置applicationContext.xml
 |