黑马程序员技术交流社区

标题: Spring相关笔记 [打印本页]

作者: 243593321    时间: 2019-9-10 14:49
标题: Spring相关笔记
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"/>
重点APIApplicationContext 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)
JdbcTemplatetx:事务
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






欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2