spring FramkWork知识点整理

Spring FramkWrok

1.介绍

  • Spring是一个IOC(DI)和AOP容器框架
  • 轻量级:Spring是非侵入性的 开发不依赖Spring的API
  • 包含:
    • 依赖注入 (DI)
    • 面向切面编程 (AOP)

2.spring 的helloworld

  • applicationContext.xml中配置

    
        
    
            
        
    
    
  • Main方法中

    //        HelloWorld helloWorld = new HelloWorld();
    //        helloWorld.setName("JIAT");
            //以上可以由spring完成
    
            //1.创建Spring的IOC对象:会对xml中设置的bean创建对象调用构造方法,并且对property标签中的属性赋值
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    
            //2.从IOC容器中获取Bean实例
    //        HelloWorld helloWorld = (HelloWorld) ctx.getBean("helloworld"); //使用id获取
            HelloWorld helloWorld = ctx.getBean(HelloWorld.class);  //使用类型获取(同类型的bean无法区分)
            //3.调用
            helloWorld.hello();
    
    

3.javaBean的注入

IOC & DI (使用的是工厂模式)

IOC: 反转资源获取的方向 原方向:组件向容器请求资源,容器返回资源;反方向:容器主动的将资源给到组件,组件要做的是选择一种合适的方式来接受资源

DI: IOC的另一种表述方式,组件以一些定义好的方式,接受来自如容器的资源注入

1.工厂方法注入bean

  • IOC容器的初始化,使用beanfactory的子接口ApplicationContext,ApplicationContext有两个主要的实现类ClassPathXmlApplicationContext(从类路径下加载配置文件)和FileSystemXmlApplicationContext(从文件系统下加载配置文件)
  • 从IOC容器中获取Bean实例
    • HelloWorld helloWorld = (HelloWorld) ctx.getBean("helloworld"); //使用id获取
    • HelloWorld helloWorld = ctx.getBean(HelloWorld.class); //使用类型获取(同类型的bean无法区分)

2.依赖注入方式

1.在xml中bean标签属性

  • Class: bean的全类名,通过反射的方式在IOC容器中创建bean,所以要求bean中必须有无参构造器
  • Id: 标识容器中的bean,id唯一

2.注入方式

属性注入和构造器注入常用,工厂方法注入很少且不推荐

  • 属性注入:利用setter方法注入bean属性值或者依赖的对象。

使用 例子如上 (需要无参构造器)

  • 构造方法注入:通过构造方法注入,保证bean在实例化之后就可以使用,在 中声明属性,没有name属性(该方法无需无参构造器)
 
        
        
          //price
    


    
        
        
         //对应maxSpeed
    
public CAR(String brand, String corp, double price) {
    this.brand = brand;
    this.corp = corp;
    this.price = price;
}


public CAR(String brand, String corp, int maxSpeed) {
    this.brand = brand;
    this.corp = corp;
    this.maxSpeed = maxSpeed;
}

细节

字面值:可以直接使用value或者constructor-arg标签中子标签value的方式,若字面值中包括特殊字符,可以使用把字面值包裹起来


    
    
        ]]>
    
    

  • 引用其他的bean:

    在property中使用ref直接引用其他bean的id

    
    

    结果如下

    Person{name='Tom', age=24, car=CAR{brand='Baoma', corp=' ', price=0.0, maxSpeed=240}}

  • 创建内部bean(无法被其他的外部bean引用)

        
            
            
    
            
                
                    
                    
                    
                
            
        
    
    
  • 注入参数详解:null值和级联属性

    可以使用专用的 为属性赋空值

    
    

    级联属性赋值:在对应的类中,要有该属性的set方法

        //需要有这一句先初始化,否则异常
    
    
  • 集合属性

    (list和数组)

  • 配置Properties,每个 标签必须定义key属性


    
        
            root
            123
            jdbc:mysql:///test
            com.mysql.jdbc.Driver
        
    

  • 单独配置集合bean,以可以被其他bean引用、

    
        
            
            
        
        
            
            
            
        
    
  • 使用p命名空间(需要声明)

    xmlns:p="http://www.springframework.org/schema/p"
    
    
        
    
  • 使用外部属性文件

    Properties

    user =root
    password =
    driverclass = com.mysql.jdbc.Driver
    jdbcurl = jdbc:mysql:///test
    

    导入文件属性

    
    

    获取文件属性用${}

    
        
        
        
        
    
    

3.自动装配

IOC容器可以自动装配bean,需要做的就是在bean的autowire属性里指定自动装配的模式

  • ByType:根据类型自动装配,如果容器中有多个与目标bean类型一致的,将无法判定,不能执行自动装配
  • ByName:根据名称自动装配,不许将目标bean的名称和属性名设置的完全相同
  • Constructor:通过构造器自动装配:当bean中存在多个构造器时很复杂



//adderss和car的beanid都必须与person类中的属性名相同 没有匹配的赋空值
public class Person {
    private String name;
    private Address address;
    private Car car;

缺点:

自动装配会配置bean中的所有属性,不够灵活

4.java bean

1.bean之间的关系

继承

    

    
定义了abstract的bean不能被实例化,只能作为模板被继承
    

    

若某一个bean没有指定class属性,则该bean必须是一个抽象bean


依赖


    
    

依赖多个时,通过逗号 空格的方式配置bean名称

2.Bean的作用域

默认为单例: scope="singleton"

    
        
        
    
public static void main(String[] args) {
//单例创建
    ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-scope.xml");
    //原型创建
Car car = (Car) ctx.getBean("car");
    Car car2 = (Car) ctx.getBean("car");
    System.out.println(car==car2);
}

5.SPEL

1.介绍

Spring表达式语言:是一个支持运行时查询和操作对象图的强大的表达式语言

语法类似EL:SpEL使用#{}作为定界符,所有在大括号里的字符都被认为是SpEL

2. 用途:

  • 通过Bean的id对bean进行引用
  • 调用方法以及引用对象中的属性
  • 计算表达式的值
  • 正则表达式的匹配

3.应用

  • 引用其他对象

    
        
        
        
    
    
  • 引用其他对象的属性

    
        
    
    
  • 支持算数运算符

    字符串+连接
    
    
  • 逻辑运算符:and,or,not,| , !

  • 比较运算符(< , > , <= , >= , == , lt , gt , eq , le , ge)

    If-else:表达式 ? ‘’ : ‘’
    
    
  • 调用静态方法或静态属性

    
            
    

6.IOC容器管理

1.IOC容器可以管理Bean的生命周期


    

  • Init和destory为类中自己定义的方法,作为初始化方法和关闭
  • 当为单例时,容器创建就调用init方法,容器关闭即 close()时,执行destroy
  • 当为原型时,只有实例化时才会调用init,每次实例化都会执行一次,容器关闭时也不会执行destroy

2.创建bean后置处理器(不需要指定id)

Bean后置处理器允许在调用初始化方法前后对bean进行额外的处理,对IOC容器中的所有bean实例逐一进行处理,而非单一实例

配置


    

继承BeanPostProcessor(bean为bean对象,beanName为bean配置的id)

public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("After init...."+ bean+","+beanName);
        if ("car".equals(beanName)){     //过滤bean
           Car car = new Car();
           car.setBrand("BaoMa");
           return car;
        }
        return bean;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("Before init..." + bean+","+beanName);
        return bean;
    }
}

7.开发中配置bean的几种方式

1.通过工厂方法配置bean

1.静态工厂

public class StaticCarFactory {
    //直接调用某一个类的静态方法,就可以返回bean的实例
    private static Map cars = new HashMap();

    static {
        cars.put("audi" , new Car("audi",300000));
        cars.put("ford" , new Car("ford",400000));
    }
    //静态工厂方法
    public static Car getCar(String name){
        return cars.get(name);
    }
}

    
          //静态方法参数输入
    

2.实例工厂

//实例工厂 的 方法,即先创建工厂本身再调用工厂的实例方法
public class InstanceCarFactory {
    private Map cars = null;

    public InstanceCarFactory() {
        cars = new HashMap();
        cars.put("audi",new Car("audi",300000));
        cars.put("ford",new Car("ford",400000));
    }

    public Car getCar(String brand){    //静态方法
        return cars.get(brand);
    }
}

    

    
        
    

2.通过FactoryBean


    
        
    
//自定义的FactoryBean需要实现FactoryBean接口
public class CarFactoryBean implements FactoryBean {
    private String brand;
    public void setBrand(String brand) {
        this.brand = brand;
    }

    //返回bean的对象
    @Override
    public Car getObject() throws Exception {
        return new Car(brand,500000);
    }
    //返回bean的类型
    @Override
    public Class getObjectType() {
        return Car.class;
    }

    //返回是否为单例
    @Override
    public boolean isSingleton() {
        return true;
    }
}

3.基于注解的方式

1.Spring能从classpath下自动扫描,侦测和实例化具有特定注解的组件。

特定组件包括:

  • @Component:基本注解,表示了一个受Spring管理的组件

  • @Respository:标识持久层组件

  • @Service:标识服务层(业务层)组件

  • @Controller:标识表现层组件

    @Service         //注解
    public class UserService {
        public  void add(){
            System.out.println("UserService add...");
        }
    }
    

对于扫描到的组件,Spring有默认的命名策略:使用非限定类名,第一个字母小写,也可以在注解中通过value属性值标识组件名称

@Repository("userRepository")   //自定义名字

2.当在组件类上使用了特定注解之后,还需要在Spring的配置文件中声明context:component-scan:


    




    



        
    

3.基于注解来配置Bean的属性

context:component-scan元素会自动注册AutowiredAnnotationBeanPostProcessor实例,该实例可以自动装配具有@Autowired 和 @Resource 、@Inject 注解的属性

@Autowired 注解自动装配具有兼容类型的单个bean属性

普通的字段以及一切具有参数的方法都可以应用@Autowired注解

private UserService userService;
@Autowired
public void setUserService(UserService userService) {
    this.userService = userService;
}
@Autowired
private UserService userService;

默认情况下,所有使用该注解的属性都需要被设置,当Spring找不到匹配的bean装配属性时,会抛出异常,若某一属性允许不被设置,可以设置注解的required属性为false

@Autowired(required = false)
private UserService userService;

当有多个类型相同的bean时,该注解会先找和注解中需要的bean名称相同的bean,若没有名称相同的bean且有多个相同类型,则会报错

  1. 装配的时候定义相同名字

  2. 利用@Qualifier的注解指定装配哪个bean:该注解还可以加到入参前面

@Autowired
@Qualifier("userRepositoryImpl")
private UserRepository userRepository;

@Resource 、@Inject与@Autowired相类似

@Resource注解要求提供一个bean名称的属性,若该属性为空,则自动采用标注处的变量或方法名作为bean的名称

@Inject 注解按类型匹配注入的bean,但没有required属性

4.Spring 4.x泛型依赖注入:

在泛型父类中建立关系,在子类中也有这个关系

public class BaseService {
    @Autowired     //父类中建立联系,其子类无需再进行装配
    protected  BaseRespository respository;

    public void add(){
        System.out.println("add...");
        System.out.println(respository);
    }
}

8.在web中的应用

Spring在web应用中使用需要额外加入jar包:

Spring-web 和Spring-webmvc

创建IOC容器:(核心思路)

  1. 非WEB应用在main方法中直接创建

  2. 实际上,Spring配置文件的名字和位置也是可以配置的!将其配置到当前web应用的初始化参数中


    
        configLocation
        applicationContext.xml
    


    
        Listeners.SpringServletContextListener
    
 
  1. 应该在web应用被服务器加载时就创建IOC容器:----监听器ServletContextListener init方法

  2. 在web应用的其他组件中如何来访问IOC容器

创建IOC容器后将其放入ServletContext(即application域中)的一个属性中

public void contextInitialized(ServletContextEvent sce) {
   //获取初始化在web配置文件中的Spring配置文件的名称和位置
   ServletContext servletContext = sce.getServletContext();
   String config = servletContext.getInitParameter("configLocation");

   //创建IOC容器
   ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
   //放入ServletContext中
   servletContext.setAttribute("ApplicationContext",ctx);

 }

调用

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //1.从application域对象中得到IOC容器的引用
    ServletContext servletContext = getServletContext();
    ApplicationContext ctx = (ApplicationContext) servletContext.getAttribute("ApplicationContext");
    //2.从IOC容器中得到需要的bean
    Person person= (Person) ctx.getBean("person");
    person.hello();
}

使用Spring封装好的接口来获取IOC

新建applicationContext.xml文件

在web配置文件中一下配置:org.springframework.web.context.ContextLoaderListener为Spring提供的API,已经完成了以上监听器的核心步骤,只需要直接从ServletContext中获取就好


    contextConfigLocation
    classpath:applicationContext.xml


    org.springframework.web.context.ContextLoaderListener

获取IOC:使用WebApplicationContextUtils. getWebApplicationContext(application)获取

  //从application中获取IOC实例
ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(application);

//从IOC容器中得到bean
Person person = ctx.getBean(Person.class);

//使用bean
person.hello();

9.Spring AOP切面编程

1.介绍

应用:

可以解决由于非业务需求(日志和验证等 )加入而引起的代码混乱

可以解决修改需求时,需要修改多个模块中相同代码,即解决代码分散的问题

2.实现

使用动态代理:使用一个代理将对象包装起来

业务代码接口-------(实现类)----------à 业务代码(类加载器)

定义一个代理,传入代理的对象(即业务代码) 完成一个返回上述类的方法

//业务代码,即需要代理的类加载器
public class ArithmeticCalculatorImpl implements ArithmeticCalculator {
    @Override
    public int add(int i, int j) {
        int result = i+j;
        return result;
    }

    @Override
    public int sub(int i, int j) {
        int result = i-j;
        return result;
    }

    @Override
    public int mul(int i, int j) {
        int result = i*j;
        return result;
    }

    @Override
    public int div(int i, int j) {
        int result = i/j;
        return result;
    }
}
//业务接口
public interface ArithmeticCalculator {
    int add(int i ,int j);
    int sub(int i ,int j);
    int mul(int i ,int j);
    int div(int i ,int j);
}
//代理器
public class ArithmeticCalculatorLoggingProxy {
    //要代理的对象
    private ArithmeticCalculator target;

    public ArithmeticCalculatorLoggingProxy(ArithmeticCalculator target) {
        this.target = target;
    }

    public ArithmeticCalculator getLoggingProxy(){
        ArithmeticCalculator proxy = null;
        //代理对象由哪一个类加载器负责加载
        ClassLoader loader = target.getClass().getClassLoader();
        //代理对象的类型,即其中有哪些方法
        Class[] interfaces = new Class[]{ArithmeticCalculator.class};

        //当调用代理对象其中的方法是,该执行的代码
        InvocationHandler h = new InvocationHandler() {
            //o : 正在返回的代理对象,一般情况下,在invoke方法中的不使用该对象
            //method:正在被调用的方法
            //args:调用方法时传入的参数

            @Override
            public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                String methodName = method.getName();
                System.out.println("The method "+methodName+" begins with "+ Arrays.asList(objects));
                int result = (int) method.invoke(target,objects);
                System.out.println("The method "+methodName+" ends with "+result);
                return result;
            }
        };
        proxy = (ArithmeticCalculator) Proxy.newProxyInstance(loader, interfaces,h);
        return  proxy;
    }
}

调用:

ArithmeticCalculator target = new ArithmeticCalculatorImpl();
ArithmeticCalculator proxy = new ArithmeticCalculatorLoggingProxy(target).getLoggingProxy();  //proxy为代理的加载器

3.AOP的概念描述

  • AOP的主要编程对象是切面,而切面模块化横切关注点,在应用AOP编程时,需要定义公共功能,但是可以明确定义这个功能在哪里,以什么方式应用,而不必修改受影响的类,如此横切关注点就模块化到特殊的对象(切面)里
  • 连接点:程序执行的某个特定位置,是个物理存在,即某个方法执行前,执行后,或抛出异常后等的点。由两个信息确认,一个是方法表示的程序执行点,一个是相对点的方位;即add()方法的连接点:执行点为add(),方位为add()方法执行前(后)的位置(一个类多个)
  • 切点:AOP通过切点定位到特定的连接点,切点通过org.springframework.aop.Pointcut描述

4.基于注解的方式配置AOP

1.AspectJ

AspectJ:最完整最流行的AOP框架

在Spring2.0以上的版本中,可以使用基于AspectJ注解或基于XML配置的AOP

要在SpringIOC容器中启用AspectJ注解支持,只要在Bean配置文件中定义一个空的XML元素aop:aspectj-autoproxy


    

2.定义切面类

带有@Aspect和@Component注解的类

通知有5个:Execution表达式@Before("execution(public int AOPImpl.ArithmeticCalculator.*(int ,int))")

修饰符 类型 包名 类名 方法名 (可以用*号来代替任意修饰符任意类型任意方法任意类,任意参数用..)

  • @Before 前置通知,方法执行前执行

    //将这个类声明为切面:
    //1.将该类放入到IOC容器中
    //2.再声明为一个切面
    
    @Aspect
    @Component
    public class LoggingAspect {
    
        //日志切面
        //声明该方法是个前置通知:在目标方法开始之前执行
        @Before("execution(public int AOPImpl.ArithmeticCalculator.*(int ,int))")
        public void beforeMethod(JoinPoint joinPoint){   //JoinPoint 连接点,可以获取目标方法信息
            String methodName = joinPoint.getSignature().getName();    //获取方法名
            List args = Arrays.asList(joinPoint.getArgs());     //获取输入参数
            System.out.println("The method"+methodName+ "begins with" + args);
        }
    }
      
      
  • @After 后置通知,方法执行后执行

    //后置通知,无论是否异常都可以执行,无法访问目标方法执行的结果
    @After("execution(public int AOPImpl.ArithmeticCalculator.*(int,int ))")
    public  void afterMethod(JoinPoint joinPoint){
        String methodName =joinPoint.getSignature().getName();
        System.out.println("The method "+methodName+ " ends.");
    
    }
    
    
  • @AfterReturning 返回通知,在方法返回结果之后执行

    /返回通知可以访问到方法的返回值,出现异常不会返回,定义一个returning
    @AfterReturning(value = "execution(public int AOPImpl.ArithmeticCalculator.*(..))",returning = "result")
    public void afterReturning(JoinPoint joinPoint,Object result){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("The method "+methodName+ " ends with "+result);
    }
    
  • @AfterThrowing 异常通知,在方法抛出异常之后执行

    //在目标方法出现异常时,会执行的代码,而且可以访问到一场对象,可以指定在出现特定异常时执行通知代码
    @AfterThrowing(value = "execution(public int AOPImpl.ArithmeticCalculator.*(..))",throwing = "ex")
    public void afterThrowing(JoinPoint joinPoint,Exception ex){  //定义ex的类型可以指定特定异常
        String methodName = joinPoint.getSignature().getName();
        System.out.println("The method "+methodName+ " occurs excetion "+ex);
    }
    
  • @Around 环绕通知,围绕着方法执行

    //环绕通知需要携带ProceedingJoinPoint类型的参数
    //环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型的参数可以决定是否执行目标方法。
    //且环绕通知必须有返回值,返回值即为目标方法的返回值
    @Around("execution(public int AOPImpl.ArithmeticCalculator.*(..))")
    public Object aroundMethod(ProceedingJoinPoint pjd){
        Object result = null;
        //执行目标方法
        try {
            //前置通知
            System.out.println("前置通知");
            result = pjd.proceed();
            System.out.println("返回通知");
        } catch (Throwable throwable) {
            //异常通知
            System.out.println("异常通知");
            //throw new RuntimeException(throwable); 抛出异常
        }
        //后置通知
        System.out.println("后置通知");
        return result;
    }
    

    3.切面的优先级

    • 切面的优先级(@Order 注解在相同目标方法的切点方法上)

    • 在切面上注解@Order(1) 数字越小优先级越高

    4.重用切面表达式

    //定义一个方法,用于声明切入点表达式,一般的,该方法中再不需要填入其他的代码
    //使用@Pointcut来声明切入点表达式
    //后面的其他通知直接使用方法名来引用当前的切入点表达式
    @Pointcut("execution(public int AOPImpl.ArithmeticCalculator.*(..))")
    public void declareJointPointExprssion(){}
    

    引用

    @Before("declareJointPointExprssion()")
    
  • 5.基于xml配置文件来配置AOP(不需要注解)

    
        
    
    
        
    
    
    
    
        
    
          
            
            
            
            
        
    
    

    10.Spring对JDBC的支持

    1.JDBC Template

    • 配置连接池

           
       
           
               
                   
                  
                   
                   
                   
               
      
      
    • 配置jdbcTemplate

    
        
            
        
    
    • Dao中直接调用jdbcTemplate的方法
    @Repository    //将DAO配置到IOC容器中
    public class EmployeeDao {
        @Autowired
        private JdbcTemplate jdbcTemplate;
    
    1. update(String sql, @Nullable Object... args)
    //测试Update方法:执行INSERT,UPDATE,DELETE
    public void testUpdate(){
        String sql = "UPDATE employees SET last_name=? WHERE id =?";
        jdbcTemplate.update(sql,"Jacke",4);
    }
    
    1. batchUpdate(String sql, List batchArgs)
    //测试batchUpdate()方法:执行update的批量更新
    //batchArgs为一个Object[]的List类型:因为修改一条记录需要一个Object数组
    public void testBatcheUpdate(){
        String sql = "INSERT INTO employees(last_name,email,dept_id) VALUES(?,?,?)";
        List batchArgs = new ArrayList<>();
    
        batchArgs.add(new Object[]{"世文","[email protected]",1});
        batchArgs.add(new Object[]{"kaixin","[email protected]",3});
        batchArgs.add(new Object[]{"CC","[email protected]",2});
        jdbcTemplate.batchUpdate(sql,batchArgs);
    }
    
    1. queryForObject(String sql, RowMapper rowMapper, @Nullable Object... args)
    //从数据库中获取一条记录,实际得到一个对应的对象
    //不是调用queryForObject(String sql, Class requiredType, Object... args) 方法
    //调用queryForObject(String sql, RowMapper rowMapper, Object... args)方法
    //1.其中RowMapper指定如何去映射结果集的行,常用的实现类为BeanPropertyRowMapper
    //2.使用SQL中列的别名完成列名和类的属性名的映射(一一对应)类似last_name--> lastName
    //3.不支持级联属性,JdbcTemplate到底是一个Jdbc的小工具,不是ORM框架
    public void testQueryForObject(){
        String sql = "SELECT id,last_name lastName,email FROM employees WHERE id = ?";
        RowMapper rowMapper = new BeanPropertyRowMapper<>(Employee.class);
        Employee employee = jdbcTemplate.queryForObject(sql,rowMapper,1);
        System.out.println(employee);
    
    }
    
    1. query(String sql, RowMapper rowMapper, @Nullable Object... args)
    //查询实体类的实体
    public  void testQueryForList(){
        String sql = "SELECT id,last_name lastName,email FROM employees WHERE id > ?";
        RowMapper rowMapper = new BeanPropertyRowMapper<>(Employee.class);
        List employees = jdbcTemplate.query(sql,rowMapper,4);
        System.out.println(employees);
    } 
    

    5.queryForObject(String sql, Class requiredType)

    //获取单个列的值,或做统计查询
    //使用queryForObject(String sql, Class requiredType) 方法
    public void testQueryForObject2(){
        String sql  = "SELECT count(id) FROM employees";
        long count = jdbcTemplate.queryForObject(sql,Long.class);
        System.out.println(count);
    }
    

    JDBCTemplate类被设计成为线程安全的,所以可以在IOC容器中去声明它的单个实例,并将这个实例注入到所有的DAO实例中

    2.NamedParameterJdbcTemplate

    在Spring JDBC模板中使用具名参数,可以取代sql语句中的?占位符(当语句中多个参数时可以使代码容易维护),在NamedParameterJdbcTemplate中得到支持

    • Xml中进行配置:
    
        
            
        
    
    • 两种方式 ,一种使用map,一种使用SqlParameterSource
    //可以为参数命名,与map中的键名一一对应,在参数多的时候不受顺序影响,便于维护
    public void testNamedPatameterJdbcTemplate(){
        String sql = "INSERT INTO employees(last_name,email,dept_id) VALUES(:ln,:email,:deptid)";
    
        Map paramMap = new HashMap<>();
        paramMap.put("email" ,"[email protected]");
        paramMap.put("deptid",3);
        paramMap.put("ln" ,2);
        namedParameterJdbcTemplate.update(sql,paramMap);
    }
    
    //使用具名参数时,可以使用update(String sql, SqlParameterSource paramSource)方法进行更新操作
    //1.语句中的参数名与对象属性名一致
    //2.使用SqlParameterSource的BeanPropertySqlParameterSource实现类作为参数
    public void testNamedPatameterJdbcTemplate2() {
        String sql = "INSERT INTO employees(last_name,email,dept_id) VALUES(:lastName,:email,:dpid)";
    
        Employee employee = new Employee();
        employee.setLastName("jdif");
        employee.setEmail("[email protected]");
        employee.setDpid(3);
    
        SqlParameterSource paramSource = new BeanPropertySqlParameterSource(employee);
        namedParameterJdbcTemplate.update(sql,paramSource);
    }
    

    11.Spring中的事务管理

    1.事务

    用来确保数据的完整性和一致性,他是一系列动作,被当作一个单独的工作单元,要么全部完成,要么全部不起作用,例如交易的时候,库存和用户余额的变化是同步的,要么一起完成,要么都不变

    Spring的核心事务管理抽象:事务管理器

    2.声明式事务:

    配置文件

    
    xmlns:tx="http://www.springframework.org/schema/tx"
    

    配置:

    
        
            
        
    
        
    

    在启用事务的方法上加事务注解

    //添加事务注解
    @Transactional
    @Override
    public void purchase(String username, String isbn) {
        //1.获取书的单价
        int price = bookShopDao.findBookPriceByIsbn(isbn);
        //2.更新书的库存
        bookShopDao.updateBookStock(isbn);
        //3.更新用户余额
        bookShopDao.updateUserAccount(username,price);
    }
    

    3.事务的属性

    ​ 事务的传播行为,事务的隔离级别,事务的回滚,只读,事务的过期时间

    1.传播行为

    传播行为:一个事务方法被另一个事务方法调用时,必须指定事务应该如何运行在另一个事务中,例如:方法可能继续在现有的事务中运行,也可能开启一个新事务,并在自己的事务中运行

    由传播属性指定,Spring定义了7种类传播行为:

    • REQUIRED(默认) 如果有事务在运行,当前的方法就在这个事务内运行,否则,就启动一个新的事物,并在自己的事务中运行 (整体停止,只要事务中的任意事务停止整个停止 exp:不能结账全部不买)
    • REQUIRED_NEW 当前的方法必须启动新事务,并在它自己的事务内运行,如果有事务正在运行,应该将它挂起 (事务中的事务通过时,部分代码正常运行 exp:不足结账,按账单顺序能买的买,不能则停止)
    • SUPPORTS 如果有事务在运行,当前方法则在这个事务内运行,否则它可以不运行在事务中
    • NOT_SUPPORTS 不能运行在事务中,如果有运行的事务,将它挂起
    • MANDATORY 必须运行在事务中,如果没有正在运行的事务,抛出异常
    • NEVER 不能运行在事务中,如果有运行的事务,抛出异常
    • NESTED 如果有事务在运行,当前方法就应该在这个事务的嵌套事务中运行,否则,就启动一个事务,在自己的事务中运行

    添加传播行为:

    //propagation指定事物的传播行为,即当前事务方法被另外一个事务方法调用时
    @Transactional(propagation = Propagation.REQUIRED)
    

    2.隔离级别

    最常用的isolation = Isolation.READ_COMMITTED
    

    3.回滚(出现异常回滚使操作停止,一般不设置)

    默认情况下Spring的声明式事务对所有的运行时异常进行回滚,也可以通过对应属性设置

    noRollbackFor 设置那个异常不回滚

    noRollbackFor = {UserAccountException.class}
    

    4.只读

    readOnly 指定是否只读,表示这个事务只读取数据但不更新数据,这样可以帮助数据库引擎优化事务,只读取数据库值的方法需要设置true

    5.过期时间

    ​ timeout 指定强制回滚之前事务可以占用的时间,当方法运行时间超过事务设置的过期时间,将会强制回滚,以s为单位

    timeout = 3    //过期时间三秒
    

    4.使用xml来配置事务

    • 先正常配置好bean
    
        
            
        
    
        
            
        
    
        
            
        
    
    • 配置管理器

      
          
              
          
      
    • 配置事务属性

    
        
            
    
                
                
                
                
            
        
    
    
        
            
            
        
    

    你可能感兴趣的:(spring FramkWork知识点整理)