注解(个人笔记)
@Compent
注解名称组合,取代原来写的那个bean的id。不用关注
包扫描,把类全找出来,看有没有关键标识,存在则设计功能
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
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.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 扫描组件,com.csi自己找去 -->
<context:component-scan base-package="com.csi" />
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.csi</groupId>
<artifactId>Spring-01-work</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.22</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.9.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.9</version>
</dependency>
</dependencies>
</project>
IoC注解
@Autowired
nb,自动注入,一开始进行一个包扫描,一旦有注解,那就是一个bean对象,先加载彼此之间的依赖性关系,看当前有没有什么属性,和有没有什么对应的依赖性关系(构造方法),用类型匹配的方式,进行传递,自动注入依赖的过程。(有构造方法可以不写@Autowired)
把构造方法删除,不写@Autowired,那没个注入。
这个类来自于Spring,把@Autowired换成@Resource警告线会消失。Spring GG了那就用@Resource ,不归属于Spring,灵活度高。但两者执行的功能是一样的。因为底层在判断时,把两个都写进去了。
byType
同一个类型有多个用@Qualifier
@Qualifier
起别名,直接调类名,它是用名称去注入,在@service上写同样的名字会报错
假如在同一个项目中,有两个或以上的类实现了UserService接口,就会产生异常,会告诉使用者在注入时根据类型找到了两个或两个以上的实现类,无法注入
解决方案是在注入是添加一个注解@Qualifier,该注解是实现通过名称辅助@Autowired,实现辅助注入
@Qualifier("XXX") 中的 XX是 Bean 的名称,所以 @Autowired 和 @Qualifier 结合使用时,自动注入的策略就从 byType 转变成 byName 了。
@Repository("userMapper")//1 @Autowired @Qualifier("userService")//2 private UserService userService
@Resource
通过名称进行装配,找不到的话可以给@service上名字,找不到名字就会采用类型匹配。
@Resource(name="userService")//肯定没错
byName(默认采用名称的匹配方式,要求变量名与被注解修饰的组件名要一直,如果不一致,就不再通过名称注入,而是采用类型的方式去注入)
如果也出现了两个实现类的情况,对于resource的解决方案是
@Service("userService") @Resource() //测试类里这是 private UserService userService @Service()//在userServiceImpl里的@Service private UserService userServiceImpl //也行,这是Service里面没有名字的情况,此时是类型注入 @Service("user") @Resource(name="user")//肯定没错
AOP注解
配置文件开启注解支持,就加包扫描
<!-- 扫描组件,com.csi自己找去 --> <context:component-scan base-package="com.csi" />
<!-- 默认是false采用jdk动态代理,如果没有接口就会采用CGlib代理,true开启自动代理,开启cglib 唉不用动 --> <!-- <aop:aspectj-autoproxy proxy-target-class="false" expose-proxy=""/>--> <aop:aspectj-autoproxy/>
//当前对象设置成组件 @Component //当前的类声明为一个切面,开启功能 @Aspect //既是一个切面,又是一个增强类 public class AOP_AnnonationTest { //定义切入点,表达式切入 @Pointcut("execution(* com.csi.service..*.*(..))") public void pointcut() {} //引用pointcut @Before("pointcut()") public void before(JoinPoint joinPoint) { System.out.println("前置通知"); } @AfterReturning(pointcut = "pointcut()",returning = "o") public void afterReturning(JoinPoint joinPoint,Object o){ System.out.println("后置通知"); } @AfterThrowing(pointcut = "pointcut()",throwing = "e") //动态代理是在执行期间产生的异常,而动态代理是在运行之后才进行代理,所以只会在运行时抛出异常 public void afterThrowing(JoinPoint joinPoint,RuntimeException e){ System.out.println("异常通知"); } @After("pointcut()") public void after(JoinPoint joinPoint){ System.out.println("最终通知"); } @Around("pointcut()") public void around(ProceedingJoinPoint pjp){ System.out.println("前"); try { Object o = pjp.proceed(); System.out.println("后"); } catch (Throwable e) { System.out.println("异常"); throw new RuntimeException(); }finally { System.out.println("最终"); } } } }
整合MyBatis(xml)
一、事务管理
事务四大特性
1.原子性
2.一致性
3.隔离性
4.持久性
隔离性
可能存在问题
-
脏读:读到了没有提交的另一个事务
导致一致性出问题,线程1开启事务,线程2也读到了,修改了,回滚报错
-
幻读:读到了已经提交的另一个事务
所以一致性不会发生变化,增加了减少了的情况,买东西,另一线程瞬间买了一个东西,出现更多的数据,幻觉,条数的变化。(一个查一个增减)
-
不可重复读:读到了已经提交的数据,但是数据的内容发生了变化,两次读取
读取一条数据,出现第一个结果,但是打印之后,数据是另一个结果(一个查一个改)
可重复读解决不了幻读,别的可以解决。(MySQL)级别高一点
已提交读(Oracle)
Spring事务传播机制(要么把别的事务干死,要么自己的事务挂起)
Spring的声明式事务
如果在同一个类中,a方法调用b方法,----->AOP拦截
如果在同一个类中,所有的方法之上都需要设计对应事务支持方式,那么,如果A方法调用了B方法,此时如何设计?
1) REQUIRED(默认属性) required
如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。
被设置成这个级别时,会为每一个被调用的方法创建一个逻辑事务域。如果前面的方法已经创建了事务,那么后面的方法支持当前的事务,如果当前没有事务会重
新建立事务。
(有事务就用,没事务就创,就用一个事务,且必须有事务)
2) MANDATORY mandatory
支持当前事务,如果当前没有事务,就抛出异常。
3) NEVER never
以非事务方式执行,如果当前存在事务,则抛出异常。
4) NOT_SUPPORTED not_suppored
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
走代码,有方法不走事务,先暂时挂起,走方法,然后再执行事务
5) REQUIRES_NEW requires_new
新建事务,如果当前存在事务,把当前事务挂起。
遇到一个其他方法那就给他创建一个事务,当前事务挂起
6) SUPPORTS supports
支持当前事务,如果当前没有事务,就以非事务方式执行。
你有就用,没有就拉倒
7) NESTED nested
支持当前事务,新增Savepoint点,与当前事务同步提交或回滚。(记录点,提供重试)
嵌套事务一个非常重要的概念就是内层事务依赖于外层事务。外层事务失败时,会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚。PROPAGATION_NESTED 与 PROPAGATION_REQUIRES_NEW的区别:它们非常类似,都像一个嵌套事务,如果不存在一个活动的事务,都会开启一个新的事务。
使用PROPAGATION_REQUIRES_NEW时,内层事务与外层事务就像两个独立的事务一样,一旦内层事务进行了提交后,外层事务不能对其进行回滚。两个事务互不影响。两个事务不是一个真正的嵌套事务。同时它需要JTA 事务管理器的支持。使用PROPAGATION_NESTED时,外层事务的回滚可以引起内层事务的回滚。而内层事务的异常并不会导致外层事务的回滚,它是一个真正的嵌套事务。
MySQL里是增加数据需要提交,不提交读不到数据,解决脏读
MySQL里是对同一个表中的同一个数据的同一个字段进行修改,两个事务进行修改,第一个事务没有提交,第二个事务只能等待,上锁了。解决可重复读
第一个事务进行修改,提交,第二个事务进行修改,未提交,目前的结果肯定是提交的,第二个事务提交了就是第二个事务的内容。