Spring学习笔记

191 阅读10分钟

Spring5

课程内容

  • spring概念
  • IOC容器
  • Aop
  • JDBCTemplate(更方便和数据库操作)
  • 事务的管理

Day1

框架概述EE

  1. Spring是一个轻量级开源的javaEE框架(开发更方便,更简洁)

  2. Spring有很多组成部分,核心部分->IOC,AOP

    (1)IOC:控制反转,创建对象的过程交给Spring管理,进行对象的实例化

    (2)AOP:面向切面,不修改源代码增强我们的功能

  3. Spring的特点: 方便解耦,简化开发,Aop编程支持,方便程序测试,方便和其他框架进行整合,降低javaApi的操作难度,方便进行事务的操作

入门案例

 @Test
    public void tess_bean1(){
        //加载配置文件
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean1.xml");
        //获取配置创建的对象
        user user = applicationContext.getBean("user", user.class);
        user.add();
    }
}
<bean id="user" class="user"></bean>
//bean的属性
//id = 变量名 
//class = new 的对象
//property 相当于给属性赋值 
//ref: 引用Spring容器中创建好的对象 
//value 具体的值, 基本数据类型!

IOC容器

IOC底层原理
  • 什么是IOC: 控制反转(inversion of control)依赖被注入到对象中 ,将对象的创建和对象之间的调用过程都交给Spring管理

  • 目的:为了耦合度降低

  • 底层的原理: xml解析,工厂模式,反射(通过得到类的字节码文件)

  • IOC:过程,进一步降低耦合度

      1.xml配置文件,配置创建的对象-->只需要修改配置文件
      2.创建工厂类,xml解析获取class属性值(类信息),通过反射创建对象class.foName(),newInstance创建对象.
    

IOC接口

  • IOC的思想基于IOC的容器,本质上就是对象的工厂
  • Spring提供了IOC容器实现的两种方式,两个接口,BeanFactory(只会加载配置文件,只有当获取或使用对象的时候才会创建对象),ApplicationContext(加载配置文件的时候,就会将配置文件中的对象创建)
    1. BeanFactory:内置的最基本的方式,是spring内部使用的接口,开发一般不使用这个
    2. ApplicationContext:beanFactory的子接口,实现更强大的功能

ApplicationContext接口中有很多的实现类: image.png

IOC容器:Bean管理XML方式(创建对象和set注入属性)

  1. 什么是bean管理:有两个操作

    1)spring创建对象
     (2)spring注入属性(构造方法和set方法)
    
  2. 管理操作的两种方式:

    (1)Xml配置文件

     1.基于xml创建对象
        <bean id="user" class="user"></bean>
         id:给对象起一个标识,通过标识获取对象
         class:创建对象所在类的全路径
         name:与id作用是一样的,区别:name中可以有特殊符号
         ref:
     
         默认执行无参数的构造方法。
     
    2. 基于xml注入属性:
        (1)DI,依赖注入就是注入属性(Di是IOC的一种实现)
        (2)有参构造注入:
        <bean id="book" class="Book">
        <constructor-arg name="bnaeme" value="算法茹姐"></constructor-arg>
        <constructor-arg name="bAthuro" value="lcc"></constructor-arg>
        </bean>
        
        index="0",也是可以替代名称的
        (3)set方法注入:
            <bean id="book" class="Book">
            <property name="bnaeme" value="算法图解"/>
            <property name="bAthuro" value="lcc"/>
            </bean>
    
    

    p名称空间注入:简化基于xml配置的方式 添加p名称空间 image.png 进行属性注入--->还是一个set方法注入 image.png

    xml注入其他属性:

    1. 字面量 设置一个空值 包含特殊符号 (1)转义(2)写入CDATA 《nanjin》

image.png

外部bean

  1. 创建两个类,service,dao,service调用dao的方法
    可以通过创建属性,再使用set方法进行注入
  2. 注入属性,内部bean和级联赋值
    部门(使用list存储员工)和员工(使用对象表示部门)是一对多的关系
    ref, bean中嵌套一个bean
  3. 注入数组属性
    细节问题,如果放进去的为对象
    公共的集合,util
  4. 自动装配:不需要写property标签,(根据属性名称->autowire.ByName或者属性类型ByType进行自动装配)
    bean的id的值和类属性名称要一样
    类型:会有类型对应多个的时候会有问题
  5. 外部属性文件
    应用:一些数据库的固定值
1.直接进行配置:连接池
    (1)引入数据库的jar包
    (2)<bean id="datasource" class="com.mysql.pool.datasource">//连接池对象
    <property name ="driverClaaName" value="com.mysql.jdbc.Driver">
    <property name="url" value="">
    <property name="usernmae">
    <property name="password">
    </bean>
2.引入外部的属性文件
    (1)property格式文件,数据库的基本信息
        jdbc.properties
            prop.driverClassName=...
            prop.url=...
            prop.username=...
            prop.password=...
    (2)引入properties文件到xml配置文件
            引入context名称空间;
            在spring中使用标签进行引入:<context:properties-placeholder 
            location="classpath:jdbc.properties"/>
            value="${prop.username}"//进行属性的引用

主要是:xml创建对象,xml注入属性

基于注解实现bean管理

  1. 什么是注解:
    (1)代码特殊标识:@注解名称(属性名称=属性值...)
    (2)在类上,方法上,属性上面均可以使用注解
    (3)让配置更加简介,更加直观

  2. bean管理创建对象的注解:
    (1)@Component: 创建对象
    (2)@Service:业务层
    (3)@Controller:web
    (4)@Respository:dao


    功能都一样:创建对象,在不同的场景使用不一样的注解是有利于理解

  3. 基于注解进行对象创建
    (1)开启组件扫描:

    <context:component-scan base-package="com.lcc"></context:component-scan>
    

    (2)在类上面写注解

    @Service(value = "userService")
    //value属性值可以省略,默认是类名称,首字母小写。
    public class UserService {
    
        public void add(){
            System.out.println("service add.......");
        }
    }
    

开启组件扫描

use-default-filters="false"
表示使用自己配置的filter
<context:component-scan base-package="com.lcc" use-default-filters="false">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

注入属性

常用注解:对象属性的注入,普通类型的注入(@Value)

命名
@Repository(value = "user")
  • @AutoWired:根据类型自动注入(Bytype)
//1、在service和dao中创建相应的注解
//2.在service中注入dao对象
@Autowired
private userDao userDao;
  • @Qualifier(根据属性名称自动注入)
//如果一个类型会有多个实现的名字,会产生错误
@Autowired
@Qualifier(value = "user")
  • @Resource(可以根据名称或者属性注入)
@Resource//默认根据类型进行注入
//根据名称注入
@Resource(name = "user")
  • @Value:普通注入属性
@Value("lcc")
private String name;

完全注解开发

  1. 创建配置类,替代xml配置文件
@Configuration//替代配置类
@ComponentScan(basePackages = {"com.lcc"})//开启包扫描
public class springConfig {

}
测试类
@Test
public void test02(){
    ApplicationContext applicationContext=new AnnotationConfigApplicationContext(springConfig.class);
    UserService userService = applicationContext.getBean("userService", UserService.class);
    System.out.println(userService);
    userService.add();
}

核心部分2 AOP

AOP的概念

定义:面向切面编程,可以对业务逻辑部分进行隔离,提高程序的可重用性,降低耦合度。

graph TD
登录功能 -->输入用户名密码-->查询数据库-->判断-->进入主页面

在登陆上增加权限判断,普通用户和管理员

  1. 原始方式:修改源代码
  2. 不修改源代码,增加新的功能,权限判断模块单独写,配置到原来有的登录上-->AOP

AOP底层原理

  • AOP面向切面编程,AOP的底层使用动态代理,增强功能 有两种情况:
    (1)有接口的情况:使用JDK的动态代理
    (2)没有接口的情况:使用CGLIB的动态代理

动态代理:

  1. 有接口:Jdk的动态代理实现:
interface userDao{
    public void login();
}
class UserDaoImpl implements userDao{
    public void login(){
        //登录的过程
    }
}

(1)创建userDao接口实现类的代理对象,通过代理对象增强功能。
2. 没有接口的情况:使用CGLIB的动态代理:创建当前user类的子类的代理对象,通过代理对象进行功能增强。

class user{
    public void add(){
    ...
    }
}
class Person extends user{
    public void add(){
    super.add();
    //增强逻辑
        ...
    }
}

AOP底层原理

  1. 使用JDK的动态代理,使用Proxy创建代理对象。
    (1)调用newProxyInstance(ClassLoader loader(类加载器),interfaces(支持的接口),InvocationHandler h(增强的逻辑))
package com.lcc.dao;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

public class JDK{
  public static void main(String[] args) {
      Class[] interfaces={userDao.class};
     /* Proxy.newProxyInstance(JDK.class.getClassLoader(), interfaces, new InvocationHandler() {
          @Override
          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
              return null;
          }
      });*/
      userDaoImpl userDao=new userDaoImpl();
      userDao o = (com.lcc.dao.userDao) Proxy.newProxyInstance(JDK.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
      o.add();
      System.out.println();
  }
}
class UserDaoProxy implements InvocationHandler{
  //将创建谁的代理对象,将对象传递过来
  //通过有参构造传递
  private Object object;
  public UserDaoProxy(Object object){
      this.object=object;
  }
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      //增强的逻辑
      //方法之前
      System.out.println("方法执行之前"+method.getName()+":传递的参数"+ Arrays.toString(args));
      //增强的方法
      Object invoke = method.invoke(object, args);
      //方法之后
      System.out.println("方法之后执行");
      return null;
  }
}

AOP操作术语

  1. 连接点:哪些方法可以被增强,都被称为连接点(理论上
  2. 切入点:实际被增强的方法
  3. 通知,增强:实际增强的部分,通知有多种类型,前置,后置,环绕,异常,最终通知
  4. 切面:是一个动作上的操作,将通知应用到切入点的过程就是切面

实现AOP操作

  • 基于AspectJ实现AOP操作
  • 什么是AspectJ:与spring框架一起使用完成AOP操作。
  • 如何实现:
    (1)基于xml
    (2)基于注解实现
  1. 引入相关的AOP的依赖
  2. 切入点的表达式
1.作用:知道对哪个类里面的方法进行增强
2:语法:
execution([权限修饰符][返回类型][类全路径][方法名称][参数列表])
eg:对com.lcc.dao.BookDao里的add进行增强
execution(*com.lcc.dao.BookDao.add(..))
eg:对com.lcc.dao.BookDao里的所有方法进行增强
execution(*com.lcc.dao.BookDao.*(..))

AspectJ注解使用

  1. 创建类,定义里面的方法
public class User {
    public void add(){
        System.out.println("add...");
    }
}

2.创建增强类,写增强的逻辑:在增强类中,创建方法,让不同方法代表不同通知类型

public class userProxy {
  public void before(){
      System.out.println("before");
  }
}

3.进行通知的配置:
(1).在spring的配置文件中,开启注解扫描
(2).使用注解创建user和userproxy对象
(3).在增强类上增加@Aspect
(4).在spring配置文件中开启生成代理对象
(5).配置不同类型的通知:在增强类的里,在作为通知方法上面添加通知类型注解,使用切入点表达式配置

image.png

image.png

重用切入点

@Pointcut(value="切入点表达式"),通过方法名进行相同切入点的应用。

多个增强类对同一方法进行增强,设置优先级,看谁先执行

@Oder(1)数值小就越先执行

AspectJ的配置文件


JdbcTemplate---Jdbc模板

定义:

  • SPring对jdbc的封装,实现对数据库的操作 准备工作
  • 引入jar包,引入依赖
  • 配置文件中配置连接池,datasource
  • 配置jdbcTemplate对象,注入datasource,
  • 在dao类中注入jabctemplate对象,并使用。
JDBCTemplate
//操作数据库
//对应数据库表创建实体类
@AutoWired
priavte JDBCTemplate jdbcTemplate;

//添加
public void add(Book book){
//update可是实现添加,修改,delete参数
    String sql = "insert into book values(?,?,?)";
    jdbcTemplate.update(sql,book.getId(),book.getName(),book.getUsatus());
    //参数是可变参数
}
//实现查询操作
//查询返回某个值
public int selectCount(){
    int res=0;
    String sql="select count(*) from user"
    Integer count=jdbcTemplate.queryForObject(sql,Integer.class);
    res=count;
    return res;
}
//返回某个对象
//RowMapper是一个接口,返回不同类型数据,使用这个接口里面实现类完成数据的封装。
public T select(String id){
     String sql="select * from user where userId=?"
     T t=jdbcTemplate.queryForObject(sql,new BeanPropertyRowMapper<T>(T.class),id);
     return t;
}

//返回集合
public List<T> selectList(){
     String sql="select * from user"
     List<T> t=jdbcTemplate.query(sql,new BeanPropertyRowMapper<T>(T.class));
     return t;
}

RowMapper是一个接口,返回不同类型数据,使用这个接口里面实现类完成数据的封装。

事务处理

  • 事务:是数据库操作的最基本单位,逻辑上一组操作,要么都成功,要么都失败
  • 事务的特性:ACID
    • 原子性:要么都成功
    • 一致性:操作之前和操作之后的总量是不变的
    • 隔离性:多事务操作的时候,不会产生影响
    • 持久性:提交之后,表的数据会发生变化。

spring操作事务

  • 操作过程:一般在service中进行事务的操作
    • 开启事务操作
    • 业务操作
    • 对异常进行捕获,回滚
    • 没有异常,提交异常
  • 在spring中有编程式和声明式处理(基于xml,基于注解方式声明式使用到了AOP原理

事务管理器 PlatFormTransactionManager

注入对象

<bean id="TranscationManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource">
    </property>
</bean>

开启事务注解

<tx:annotation-driven transaction-manager="TranscationManager"></tx:annotation-driven>

在service类中添加事务注解

@Transactional
//可以添加到类上,也可以式方法上

事务操作之参数配置

  • progation:事务传播行为:多事务进行修改时,应该是怎么处理

image.png

  • ioslation:事务隔离级别

image.png

  • timeout:超时时间
  • readOnly:是否只读
  • rollbackFor:回滚

xml配置

image.png

<aop:config>
//配置切入点
    <aop:pointcut id="pt" expression="execution(* com.lcc.service.UserService.*(..))"/>
    //配置切面 
    <aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/>
</aop:config>

课程总结

  • Spring框架概念
    • 为了解决企业复杂性,两个核心组成:IOC和AOP
  • IOC容器
    • IOC底层原理:工厂和反射
    • BeanFactory
    • IOC操作Bean管理(基于xml)
    • IOC操作Bean管理(基于注解)
  • AOP
    • AOP底层原理:动态代理
    • 切入点,增强,通知,切面
    • AspectJ实现AOP的操作
  • JdbcTemplate
    • 使用jdbcTemplate实现对数据库的CURD的操作
    • 实现对数据库的批量操作
  • 事务管理
    • 事务的概念,和特性
    • 声明事务管理基于注解方式实现