Spring框架入门

Spring框架入门

一、IOC容器

1、概念

IOC:Inversion of Control 控制反转
DI:Dependency Injection 依赖注入
控制反转,从字面意思来看,就是控制权又被动变主动,最后又变回被动。
举个例子:
你的主管要求你做一件事情,这个时候就存在这么几个过程:

  • 主管命令你做事情(这个时候主动权在主管,你是被动的)

  • 你接到命令做事情(这个时候主题是你,你是主动的,控制权在你手里)

  • 你完成事情(这个时候主题依然是你,控制权在你手里)

  • 报告主管做完事情(主动权又叫交到主管手里了)


  • 什么是IOC
    • 控制反转,把对象创建和对象之间的调用过程,交给Spring进行管理
    • 使用IOC目的:为了耦合度降低
    • 做入门案例就是IOC实现
  • IOC底层原理
    • xml解析、工厂模式、反射
2、IOC的基本应用
<!--1 set方法注入属性-->
    <bean id="user" class="com.spring.pojo.User">
        <!--它会调用User的set方法-->
        <property name="name" value="tang"></property>
        <property name="age" value="19"></property>
    </bean>
    
    <!--调用有参构造器-->
    <bean id="user" class="com.spring.pojo.User">
        <constructor-arg value="tang" name="name"></constructor-arg>
        <constructor-arg name="age" value="18"></constructor-arg>
    </bean>
    
        <bean class="com.spring.pojo.User" id="user">
        <!--null值-->
        <!--<property name="name">
            <null/>
        </property>
        <property name="age">
            <value>12</value>
        </property>-->

        <property name="name">
            <!--<value><![CDATA[<tang>]]></value>-->
            <value>&lt;&gt;</value>
        </property>
    </bean>
    
    <!--
         set方法,bean标签进行
        要先添加一个名称命名空间,如下:
        xmlns:p="http://www.springframework.org/schema/p"
        
        xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
    -->
    <bean id="user" class="com.spring.pojo.User" p:name="tang" p:age="19"></bean>
    
	@Test
    public void service() {
        //创建xml的实例
        ApplicationContext context = new ClassPathXmlApplicationContext("Bean2.xml");
        UserService userService = (UserService) context.getBean("userService");
        userService.service();
    }

自动装配

`	<!--自动装配:
        autowire:
            byName 根据名称自动装配
            byType 根据类型自动装配
    -->
    <bean id="user" class="com.dojo.User" autowire="byType">
        <property name="age" value="19"></property>
        <property name="name" value="tang"></property>
    </bean>
    <bean id="depart" class="com.dojo.Depart" p:name="人事部门"></bean>
3、生命周期
  • 生命周期
    • 从对象创建到对象销毁的过程
  • bean生命周期
    • 通过构造器创建bean实例(无参数构造)
    • 为bean的属性设置值和对其他bean引用(调用set方法)
    • 调用bean的初始化的方法(需要进行配置初始化的方法)
    • bean可以使用了(对象获取到了)
    • 当容器关闭时候,调用bean的销毁的方法(需要进行配置销毁的方法)
	<bean id="order" class="com.dojo.order" init-method="initMethod" destroy-method="destroyMethod">
        <property name="order" value="tang"></property>
    </bean>

    <!--后置处理方法,所有对象都要经过-->
    <bean id="myBean" class="com.processor.MyBeanPost"></bean>
//后置处理方法
public class MyBeanPost implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("后置处理器的Before方法");
        return null;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("后置处理器的After方法");
        return null;
    }
}
//实例方法
public class order {
    private String order;
    public order(){
        System.out.println("无参构造执行了");
    }

    public void setOrder(String order) {
        System.out.println("set方法执行了");
        this.order = order;
    }

    public void initMethod(){
        System.out.println("initMethod方法执行了");
    }
    public void destroyMethod(){
        System.out.println("destroyMethod方法执行了");
    }
}
3、注入多种类型
	<bean id="data" class="com.dojo.Data">
        <!--int[] 类型-->
        <property name="array">
            <array>
                <value>java基础</value>
                <value>MySQL数据库基础</value>
            </array>
        </property>
        <!--list类型-->
        <property name="list" ref="booklist">
            <!--<list>
                <value>鸭头</value>
                <value>鸭腿</value>
                <value>鸭脖</value>
            </list>-->
        </property>


        <property name="map">
            <map>
                <entry key="java" value="Java基础"></entry>
                <entry key="MySQL" value="MySQL数据库"></entry>
            </map>
        </property>

        <property name="set">
            <set>
                <value>Java</value>
                <value>MySQL</value>
                <value>Spring</value>
            </set>
        </property>

        <!--向list中填入对象-->
        <property name="userList">
            <list>
                <ref bean="user1"></ref>
                <ref bean="user2"></ref>
            </list>
        </property>
    </bean>

    <!--(2)使用util标签完成list集合注入提取-->
    <util:list id="booklist">
        <value>易筋经</value>
        <value>九阴真经</value>
        <value>九阳神功</value>
    </util:list>

    <bean id="user1" class="com.dojo.User" p:name="tang" p:age="19"></bean>
    <bean id="user2" class="com.dojo.User" p:name="lixiang" p:age="18"></bean>
4、工厂Bean(FactoryBean)
  • Spring有两种类型bean,一种普通bean,另外一种工厂bean(FactoryBean)
  • 普通bean:在配置文件中定义bean类型就是返回类型
  • 工厂bean:在配置文件定义bean类型可以和返回类型不一样第一步创建类,让这个类作为工厂bean,实现接口FactoryBean第二步实现接口里面的方法,在实现的方法中定义返回的bean类型
public class MyBean implements FactoryBean<Course> {//定义返回bean 要返回的类型
    @Override
    public Course getObject() throws Exception {
        Course course = new Course();
        course.setCname("abc");
        return course;
    }
    @Override
    public Class<?> getObjectType() {
        return null;
    }
    @Override
    public boolean isSingleton() {
        return false;
    }
}
@Test
public void test3() {
    ApplicationContext context =new ClassPathXmlApplicationContext("bean3.xml");
    Course course = context.getBean("myBean", Course.class);
    System.out.println(course);
}
<bean id="myBean" class="com.atguigu.spring5.factorybean.MyBean"></bean>
5、如何设置单实例还是多实例
  • 在spring配置文件bean标签里面有属性(scope)用于设置单实例还是多实例
  • scope属性值第一个值默认值,singleton,表示是单实例对象第二个值prototype,表示是多实例对象
<!--scope创建实例对象,单例还是多例 默认singleton:单例,proptotye : 多例-->
<bean id="myBean" class="com.factoryBean.MyBeans" scope="prototype"></bean>

二、AOP操作

1、AOP概念

(1)什么是AOP

  • 面向切面编程(方面),利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
  • 通俗描述:不通过修改源代码方式,在主干功能里面添加新功能
2、动态代理
public class JDKProxy{
    public static void main(String[] args) {
        UserImpl userImpl = new UserImpl();
        UserImplProxy implProxy = new UserImplProxy(userImpl);
        //获取被代理类的所有接口
        Class[] interfaces = userImpl.getClass().getInterfaces();
        //加载器
        ClassLoader classLoader = userImpl.getClass().getClassLoader();
        UserDao proxy = (UserDao) Proxy.newProxyInstance(classLoader,interfaces,implProxy);
        int add = proxy.add(2, 7);
        System.out.println(add);
    }
}

class UserImplProxy implements InvocationHandler{
    private Object object;
    public UserImplProxy(Object obj){
        this.object = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("执行前操作,method:" + method.getName() + ",参数是:" + Arrays.toString(args));
        Object invoke = method.invoke(object, args);
        System.out.println("执行后操作," + object);
        return invoke;
    }
}
3、AOP术语
  • 连接点

    • 类里面的哪些方法可以被增强,这些方法称为连接点
  • 切入点

    • 实际被真正增强的方法
  • 通知

    • 实际增强
4、AOP操作
  • Spring框架一般都是基于AspectJ实现AOP操作

    • AspectJ不是Spring组成部分,独立AOP框架,一般把AspectJ和Spirng框架一起使用,进行AOP操作
  • 基于AspectJ实现AOP操作

    • 基于xml配置文件实现
    • 基于注解方式实现(使用)
  • 切入点表达式

    • 切入点表达式作用:知道对哪个类里面的哪个方法进行增强

    • 语法结构:execution([权限修饰符] [返回类型] [类全路径] 方法名称 )

      • 举例1:对com.atguigu.dao.BookDao类里面的add进行增强execution(*com.atguigu.dao.BookDao.add(…))

      • 举例2:对com.atguigu.dao.BookDao类里面的所有的方法进行增强execution(*com.atguigu.dao.BookDao.(…))

      • 举例3:对com.atguigu.dao包里面所有类,类里面所有方法进行增强execution(*com.atguigu.dao..*(…))

5、AOP操作(AspectJ注解)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                           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">

    <!--扫描注解-->
    <context:component-scan base-package="com.proxy,com.dao"></context:component-scan>

    <!--开启Aspect生成代理对象-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

</beans>
@Component //编译注解
@Aspect //生成代理类对象
public class UserProxy {
    //@Before 表示前置通知 里面的value表示为特定
    @Before(value = "execution(* com.dao.User.add(..))")
    public void before(){
        System.out.println("before方法执行了.....");
    }

    //后置通知
    @After(value = "execution(* com.dao.User.add())")
    public void after(){
        System.out.println("after方法执行了......");
    }

    //后置返回通知
    @AfterReturning(value = "execution(* com.dao.User.add())")
    public void afterReturning(){
        System.out.println("afterReturning方法执行了......");
    }

    //环绕通知
    @Around(value = "execution(* com.dao.User.add())")
    public void around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("环绕之前......");
        pjp.proceed();
        System.out.println("环绕之后......");
    }

    //后置错误通知
    @AfterThrowing(value = "execution(* com.dao.User.add())")
    public void afterThrowing(){
        System.out.println("AfterThrowing......");
    }
}
  • 相同切入点抽取
@Component
@Aspect //生成代理类对象
public class UserProxy {
    //相同切入点提取出来
    @Pointcut(value = "execution(* com.dao.User.add(..))")
    public void pointDom(){

    }

    //@Before 表示前置通知 里面的value表示为特定
    @Before(value = "pointDom()")
    public void before(){
        System.out.println("before方法执行了.....");
    }

    @After(value = "pointDom()")
    public void after(){
        System.out.println("after方法执行了......");
    }

    @AfterReturning(value = "pointDom()")
    public void afterReturning(){
        System.out.println("afterReturning方法执行了......");
    }

    @Around(value = "pointDom()")
    public void around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("环绕之前......");
        pjp.proceed();
        System.out.println("环绕之后......");
    }

    @AfterThrowing(value = "pointDom()")
    public void afterThrowing(){
        System.out.println("AfterThrowing......");
    }
}

  • 优先级
    • 有多个增强类对同一个方法进行增强,设置增强类优先级
      • 在增强类上面加增强类注解Order(数字),数字越小,优先级越高
@Component
@Aspect
@Order(1) //优先级设置,越小优先级越高
public class UserOrder {
    @Before(value = "execution(* com.dao.User.add())")
    public void before(){
        System.out.println("UserOrder的Before方法执行了...");
    }
}
  • AspectJ的xml配置

    首先写两个实例类

    public class Book {
        public void add(){
            System.out.println("add.............");
        }
    }
    
    public class BookProxy {
        public void Before(){
            System.out.println("Before...........");
        }
    }
    

    xml配置

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:aop="http://www.springframework.org/schema/aop"
           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">
    
        <bean id="book" class="com.xmlProxy.Book"></bean>
        <bean id="bookProxy" class="com.xmlProxy.BookProxy"></bean>
    
        <!--配置aop增强-->
        <aop:config>
            <!--切入点-->
            <aop:pointcut id="p" expression="execution(* com.xmlProxy.Book.add())"/>
    
            <!--配置切面-->
            <aop:aspect ref="bookProxy">
                <!--增强指定方法-->
                <aop:before method="Before" pointcut-ref="p"></aop:before>
            </aop:aspect>
        </aop:config>
    </beans>
    

    测试方法

    @Test
        public void test1(){
            ApplicationContext context = new   ClassPathXmlApplicationContext("bean2.xml");
            Book book = context.getBean("book", Book.class);
            book.add();
        }
    
  • 完全注解配置
    @Configurable
    //组件扫描
    @ComponentScan(value = {"com"})
    //开启Aspect 生成代理类
    @EnableAspectJAutoProxy(proxyTargetClass = true)
    public class configAop {
    }
    

    测试类

    @Test
    public void test2(){
        ApplicationContext context = new AnnotationConfigApplicationContext(configAop.class);
        User user = context.getBean("user", User.class);
        user.add();
    }
    

三、JdbcTemplate

  • 要用到的jar包
  • 在这里插入图片描述
1、xml配置
	<context:component-scan base-package="com.dao,com.service"/>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/test"/>
        <property name="username" value="root"/>
        <property name="password" value="123"/>
    </bean>

    <!--创建JdbcTemplate-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
2、增加操作
@Service
public class BookService {
    @Autowired 
    private BookDao bookDao;

    //添加操作
    public int addBook(Book book){
        return bookDao.add(book);
    }
}

//BookTest类
public class BookTest {
    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        BookService bookService = context.getBean("bookService", BookService.class);
        Book book = new Book(null,"java基础","tang");
        int i = bookService.addBook(book);
        System.out.println(i);
    }
}

//BookDaoImpl 类
@Repository
public class BookDaoImpl implements BookDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public int add(Book book) {
        String sql = "insert into book(id,name,author) value(?,?,?)";
        return jdbcTemplate.update(sql,book.getId(),book.getName(),book.getAuthor());
    }
}
3、更新与删除
//BookService
//更新书籍
    public int updateBook(Book book){
        return bookDao.update(book);
    }

    public int deleteBook(int id){
        return bookDao.delete(id);
    }
//BookService
 	@Override
    public int update(Book book) {
        String sql = "update book set name=?,author=? where id=?";
        return jdbcTemplate.update(sql,book.getName(),book.getAuthor(),book.getId());
    }

    @Override
    public int delete(int id) {
        String sql = "delete from book where id=?";
        return jdbcTemplate.update(sql,id);
    }
//测试类
	@Test
    public void test1(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        BookService bookService = context.getBean("bookService", BookService.class);
        Book book = new Book(1,"java基础","小菜鸟");
        bookService.updateBook(book);
    }

    @Test
    public void test2(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        BookService bookService = context.getBean("bookService", BookService.class);
        //Book book = new Book(1,"java基础","小菜鸟");
        bookService.deleteBook(1);
    }
4、获取数据的数量
//BookDaoImpl
	@Override
    public int queryCount() {
        String sql = "select count(*) from book";
        return jdbcTemplate.queryForObject(sql,Integer.class);
    }

//BookService
	//返回数据的数量
    public int queryBookCount(){
        return bookDao.queryCount();
    }
5、获取所有数据
//BookService
	@Override
    public List<Book> queryAll() {
        String sql = "select * from book";
        return jdbcTemplate.query(sql,new BeanPropertyRowMapper<>(Book.class));
    }

 	@Test
    public void test4(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        BookService bookService = context.getBean("bookService", BookService.class);
        List<Book> book = bookService.queryAllBook();
        System.out.println(book);
    }
6、批量操作

batchUpdate(sql,List<Object[]>)

//BookService
	@Override
    public void batchAdd(List<Object[]> batchArgs) {
        String sql = "insert into book(id,name,author) value(?,?,?)";
        jdbcTemplate.batchUpdate(sql,batchArgs);
    }

//批量操作
    public void batchAddBook(List<Object[]> batchArgs){
        bookDao.batchAdd(batchArgs);
    }

	@Test
    public void test5(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        BookService bookService = context.getBean("bookService", BookService.class);
        List<Object[]> batchArgs = new ArrayList<>();
        Object[] obj1 = {3,"java高级","li"};
        Object[] obj2 = {4,"jdbc","li"};
        batchArgs.add(obj1);
        batchArgs.add(obj2);
        bookService.batchAddBook(batchArgs);
    }

四、事务操作

1、事务是什么

​ 事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消。也就是事务具有原子性,一个事务中的一系列的操作要么全部成功,要么一个都不做。

2、事务的四大特性

数据库事务 (transanction) 正确执行的四个基本要素。ACID,原子性(Atomicity)、一致性(Correspondence)、隔离性(Isolation)、持久性(Durability)。

​ (1)原子性:整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
​ (2)一致性:在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。
​ (3)隔离性:隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。如果有两个事务,运行在相同的时间内,执行 相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用系统。这种属性有时称为串行化,为了防止事务操作间的混淆, 必须串行化或序列化请 求,使得在同一时间仅有一个请求用于同一数据。
​ (4)持久性:在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。

3、消费功能
@Repository
public class UserDaoImpl implements UserDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * 消费
     * @param id 要消费的id
     * @param count 消费的钱
     */
    @Override
    public void reduceMoney(int id,int count) {
        String sql = "update user set money=money-? where id=?";
        jdbcTemplate.update(sql,count,id);
    }

    @Override
    public void addMoney(int id,int count) {
        String sql = "update user set money=money+? where id=?";
        jdbcTemplate.update(sql,count,id);
    }

    @Override
    public int queryMoney(int id) {
        String sql = "select money from user where id=?";
        return jdbcTemplate.queryForObject(sql,Integer.class,id);
    }
}


@Service
public class UserService {
    @Autowired
    private UserDao userDao;
    /**
     * 消费
     * @param consumer 消费的人的id
     * @param producer 生产者的id
     * @param count 消费的金额
     */
    public void countChange(int consumer,int producer,int count){
        int money = userDao.queryMoney(consumer);
        if (money >= count){
            userDao.reduceMoney(consumer,count);
            userDao.addMoney(producer,count);
        }else {
            System.out.println("余额不足...");
        }
    }
}
4、添加事务

用注解声明法添加事务

在service类上面(或者service类里面方法上面)添加事务注解

(1)@Transactional,这个注解添加到类上面,也可以添加方法上面

(2)如果把这个注解添加类上面,这个类里面所有的方法都添加事务

(3)如果把这个注解添加方法上面,为这个方法添加事务

  • xml
<!--创建事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--开启事务注解-->
    <tx:annotation-driven transaction-manager="transactionManager"/>
  • userService
@Service
@Transactional //事务注解
public class UserService {
    @Autowired
    private UserDao userDao;
    /**
     * 消费
     * @param consumer 消费的人的id
     * @param producer 生产者的id
     * @param count 消费的金额
     */
    public void countChange(int consumer,int producer,int count){
        int money = userDao.queryMoney(consumer);
        if (money >= count){
            userDao.reduceMoney(consumer,count);
            int n = 10/0;
            userDao.addMoney(producer,count);
        }else {
            System.out.println("余额不足...");
        }
    }
}
5、@Transactional
public @interface Transactional {
    @AliasFor("transactionManager")
    String value() default ""; //可选,指定事务的事务管理器

    @AliasFor("value")
    String transactionManager() default ""; 

    Propagation propagation() default Propagation.REQUIRED;//可选,事务的传播行为

    Isolation isolation() default Isolation.DEFAULT; //可选,事务的隔离级别

    int timeout() default -1; //事务超出时间设置

    boolean readOnly() default false; //读写或只读事务,默认读写

    Class<? extends Throwable>[] rollbackFor() default {}; //导致事务回滚的异常数组,可选

    String[] rollbackForClassName() default {}; //导致事务回滚的异常类的名字,可选

    Class<? extends Throwable>[] noRollbackFor() default {}; //不会导致事务回滚的异常数组,可选

    String[] noRollbackForClassName() default {}; //不会导致事务回滚的异常类名的数组,可选
}
  • 事务级别 isolation
事务级别事务名称含义
Read uncommitted脏读就是一个事务可以读取另一个未提交事务的数据
Read committed不可重复读就是一个事务要等另一个事务提交后才能读取数据。
Repeatable read幻读重复读,就是在开始读取数据(事务开启)时,不再允许修改操作
Serializable串行化读,事务只能一个一个执行,效率慢

脏读:一事务对数据进行了增删改,但未提交,另一事务可以读取到未提交的数据。如果第一个事务这时候回滚了,那么第二个事务就读到了脏数据。
不可重复读:一个事务中发生了两次读操作,第一次读操作和第二次操作之间,另外一个事务对数据进行了修改,这时候两次读取的数据是不一致的。
幻读:第一个事务对一定范围的数据进行批量修改,第二个事务在这个范围增加一条数据,这时候第一个事务就会丢失对新增数据的修改。

  • 事物的传播 propagation
事物的传播类型说明
REQUIRED如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
SUPPORTS支持当前事务,如果没有当前事务,就以非事务方法执行。
MANDATORY使用当前事务,如果没有当前事务,就抛出异常。
REQUIRES_NEW新建事务,如果当前存在事务,把当前事务挂起。
NOT_SUPPORTED以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
NEVER以非事务方式执行操作,如果当前事务存在则抛出异常。
NESTED如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与propagation_required类似的操作

mandatory(强制性的 )

@Service
@Transactional(isolation = Isolation.REPEATABLE_READ,propagation = Propagation.REQUIRED)
//事务注解
public class UserService {
    @Autowired
    private UserDao userDao;
    /**
     * 消费
     * @param consumer 消费的人的id
     * @param producer 生产者的id
     * @param count 消费的金额
     */
    public void countChange(int consumer,int producer,int count){
        int money = userDao.queryMoney(consumer);
        if (money >= count){
            userDao.reduceMoney(consumer,count);
            int n = 10/0;
            userDao.addMoney(producer,count);
        }else {
            System.out.println("余额不足...");
        }
    }
}
6、xml配置事务
<!--创建事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--开启事务注解-->
    <tx:annotation-driven transaction-manager="transactionManager"/>

    <!--配置事务参数-->
    <tx:advice id="txAdvice">
        <tx:attributes>
            <!--制定哪种方法上添加事务-->
            <tx:method name="countChange" propagation="REQUIRED"/>
            <!--<tx:method name="count*"/>-->
        </tx:attributes>
    </tx:advice>

    <!--设置切入点和切面-->
    <aop:config>
        <!--切入点-->
        <aop:pointcut id="pt" expression="execution(* com.service.UserService.*(..))"/>
        <!--设置切面-->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/>
    </aop:config>
7、完全注解开发
@Configurable //配置类
@ComponentScan(basePackages = "com") //组件扫描
@EnableTransactionManagement //开启事务
public class UserConfig {
    @Bean
    public DruidDataSource getDruidDataSource(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/person");
        dataSource.setUsername("root");
        dataSource.setPassword("123");
        return dataSource;
    }

    //创建jdbcTemplate 对象
    @Bean
    public JdbcTemplate getJdbcTemplate(DataSource dataSource){
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(dataSource);
        return jdbcTemplate;
    }

    //创建事务管理器
    @Bean
    public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource){
        DataSourceTransactionManager manager =
            new DataSourceTransactionManager();
        manager.setDataSource(dataSource);
        return manager;
    }
}


@Test
public void countChange1(){
    ApplicationContext context = 
        new AnnotationConfigApplicationContext(UserConfig.class);
    UserService userService = 
        context.getBean("userService", UserService.class);
    userService.countChange(1,2,100);
}

五、spring5的新特性

1、log4j2

需要的包
在这里插入图片描述

xml配置

<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration后面的status用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,可以看到log4j2内部各种详细输出-->
<configuration status="DEBUG">
    <!--先定义所有的appender-->
    <appenders>
        <!--输出日志信息到控制台-->
        <console name="Console" target="SYSTEM_OUT">
            <!--控制日志输出的格式-->
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </console>
    </appenders>
    <!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
    <!--root:用于指定项目的根日志,如果没有单独指定Logger,则会使用root作为默认的日志输出-->
    <loggers>
        <root level="info">
            <appender-ref ref="Console"/>
        </root>
    </loggers>
</configuration>
public class Log4J {
    private static final Logger log = LoggerFactory.getLogger(Log4J.class);

    public static void main(String[] args) {
        log.warn("\nlog4J Hello\n");
        log.info("\nlog4J Hello\n");
    }
}
2、@Nullable 注解

@Nullable 注解可以使用在方法、属性、参数上面,表示方法返回可以为空,属性值可以为空,参数值可以为空

3、函数式编程

GenericApplicationContext

//函数式编程,交给spring处理
public class GenericApplicationContextTest {
    public static void main(String[] args) {
        //创建GenericApplicationContext对象
        GenericApplicationContext context = new GenericApplicationContext();
        //调用context对象的方法注册
        context.refresh();
        context.registerBean("user", User.class,()->new User("tang"));
        //获取对象的方法
        User user = context.getBean("user", User.class);
        System.out.println(user);
    }
}
4、测试类

在这里插入图片描述

JTest4

@RunWith(SpringJUnit4ClassRunner.class) //加载单元测试类的框架
@ContextConfiguration("classpath:bean1.xml") //加载配置文件
public class SpringTest {
    @Autowired
    private UserService userService;

    @Test
    public void test(){
        userService.countChange(1,2,100);
    }
}

JTest5

//@ExtendWith(SpringExtension.class) //JTest5操作
//@ContextConfiguration("classpath:bean1.xml")
@SpringJUnitConfig(locations = "classpath:bean1.xml") //复合注解,等同于上面个两个
public class JTest5 {
    @Autowired
    private UserService userService;
    @Test
    public void test(){
        userService.countChange(1,2,100);
    }
}


       //创建GenericApplicationContext对象
        GenericApplicationContext context = new GenericApplicationContext();
        //调用context对象的方法注册
        context.refresh();
        context.registerBean("user", User.class,()->new User("tang"));
        //获取对象的方法
        User user = context.getBean("user", User.class);
        System.out.println(user);
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值