Java-Spring5配置详解(下)

12 篇文章 0 订阅
10 篇文章 0 订阅

写在前面

  • 本文是基于我的上一篇笔记“Spring5笔记(上)”进行的知识点补充,绝大多数知识点已经合并到上一篇里。

手动创建Spring项目(非Maven托管)

  • idea中创建普通Java项目(或module)
  • 下载Spring离线jar包,并手动按需导入(导入方法此处省略),其中必须的包为:
    • spring-aop
    • spring-beans
    • spring-context
    • spring-core
    • spring-expression
    • commons-logging
      • 这个包需要单独下载,而且必须要导入,否则运行时idea会报错找不到包。
  • 接下来正常写代码即可。

IOC-工厂bean

  • Spring的bean有两种类型:普通bean、工厂bean(FactoryBean)
  • 普通bean(前边所讲都是普通bean),在配置文件中定义的bean类型就是返回的类型
  • 工厂bean,在配置文件中定义的bean类型可以和返回类型不一样
    • 创建类,让这个类作为工厂bean,实现FactoryBean这个接口
    • 实现接口里的方法,在方法getObject()中定义返回的bean类型
    • 核心代码
      public class MyBean implements FactoryBean<User> {
          @Autowired
          private User user;
          public User getUser() {
              return user;
          }
          public void setUser(User user) {
              this.user = user;
          }
          public User getObject() throws Exception {
              return this.user;
          }
          public Class<?> getObjectType() {
              return null;
          }
          public boolean isSingleton() {
              return false;
          }
      }
      

IOC-bean的生命周期(主要分5步)

  • 通过构造器创建bean实例(无参构造器)
  • 给bean中的属性赋值和对其他bean引用(set方法)
  • 调用bean的初始化的方法(需要进行配置初始化的方法)
    • 在bean的类中创建myInitMethod()方法
    • 在配置文件bean中指定init-method所要调用的方法
  • bean可以使用了(对象获取到了)
  • 当容器关闭时调用bean的销毁的方法(需要进行配置销毁的方法)
    • 在bean的类中创建myDestroyMethod()方法
    • 在配置文件bean中指定init-method所要调用的方法
  • 核心代码
    <bean id="myBean" class="cn.cnyasin.pojo.MyBean" init-method="myInitMethod" destroy-method="myDestroyMethod"/>
    
  • 补充:在调用bean初始化方法前后还可以分别添加两步:把bean实例传递给bean的后置处理器的方法,了解一下,此处省略

IOC-配置引入外部属性文件(*.properties),以注册Druid数据库连接池为例

  • 导入依赖包:druid-1.2.6.jar、mysql-connector-java-5.1.39-bin.jar
  • 方式一:默认配置文件直接加载
    <!-- 注册Druid的bean方式一:默认配置文件直接加载 -->
    <bean id="druid" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/jdbc_test?useSSL=false"/>
        <property name="username" value="root"/>
        <property name="password" value="rootroot"/>
    </bean>
    
  • 方式二:引入外部属性文件
    • 添加context约束
    • 在资源目录下新建jdbc.properties文件
      jdbc.driverClassName=com.mysql.jdbc.Driver
      jdbc.url=jdbc:mysql://localhost:3306/jdbc_test?useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai
      jdbc.username=root
      jdbc.password=root
      
    • 配置读取jdbc.properties文件
      <!-- 注册Druid的bean方式二:引入外部属性文件 -->
      <context:property-placeholder location="classpath:jdbc.properties"/>
      <bean id="druid" class="com.alibaba.druid.pool.DruidDataSource">
          <property name="driverClassName" value="${jdbc.driverClassName}"/>
          <property name="url" value="${jdbc.url}"/>
          <property name="username" value="${jdbc.username}"/>
          <property name="password" value="${jdbc.password}"/>
      </bean>
      
    • 使用bean
      public static void main(String[] args) throws SQLException {
          ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
          DruidDataSource druid = (DruidDataSource) context.getBean("druid");
          System.out.println(druid.getConnection());
      }
      

IOC-注解组件扫描配置

  • 常用配置
    • use-default-filters:是否使用默认filter,默认true
    • context:include-filter:设置扫描哪些内容
    • context:exclude-filter:设置不扫描哪些内容
  • 核心代码
    <!-- 组件扫描配置一:
    use-default-filters:是否使用默认filter,默认true
    context:include-filter:设置扫描哪些内容
    -->
    <context:component-scan base-package="cn.cnyasin.pojo" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
    
    <!-- 组件扫描配置二:
    context:exclude-filter:设置不扫描哪些内容
    -->
    <context:component-scan base-package="cn.cnyasin.pojo">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
    

JdbcTemplate

  • 新建module手动导入包,在原有的基本包的基础上还需要导入以下几个包
    • spring-jdbc.jar
    • spring-orm.jar
    • spring-tx.jar
  • 在配置中注册数据库连接池(参考之前的笔记)
  • 在配置中开启自动扫描包(参考之前的笔记)
  • 在配置中注册JdbcTemplate对象并注入dataSource
    <!-- JdbcTemplate对象 -->
    <bean id="jdbc" class="org.springframework.jdbc.core.JdbcTemplate">
        <!-- 注入dataSource -->
        <property name="dataSource" ref="druid"/>
    </bean>
    
  • 数据库创建好表book(略)
  • 创建service、dao、entity并配好注解,以添加一条数据为例:
    public interface BookDao {
        public void add(Book book);
    }
    @Repository
    public class BookDaoImpl implements BookDao{
        @Autowired
        private JdbcTemplate jdbcTemplate;
        @Override
        public void add(Book book) {
            String sql = "insert into book (`name`, `status`,`created_at`) values (?,?,?)";
            Object[] args = {book.getName(), book.getStatus(),book.getCreated_at()};
            int update = jdbcTemplate.update(sql, args);
            System.out.println(update);
        }
    }
    @Service
    public class BookService {
        @Autowired
        private BookDao bookDao;
        public void addBook(Book book){
            bookDao.add(book);
        }
    }
    public class Book {
        private int id;
        private String name;
        private int status;
        private Long created_at;
        public static final int STATUS_OFF = 0;
        public static final int STATUS_ON = 1;
        //getter、setter...
    }
    public class MyTest {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
            BookService bookService = context.getBean("bookService", BookService.class);
            // 当前时间戳秒
            long time = new Date().getTime() / 1000;
            bookService.addBook(new Book("红楼梦", Book.STATUS_OFF, time));
        }
    }
    
  • 删除、修改方法与添加一样,这里省略
  • 查询某个值的方法:jdbcTemplate.queryForObject(sql, Integer.class);
  • 查询某个对象的方法:jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Book>(Book.class), id);
    • 第二个参数:传RowMapper的一个实现类,RowMapper的不同实现类返回不同类型的数据,这里目前使用固定这个类即可
  • 查询集合的方法:jdbcTemplate.query(sql, new BeanPropertyRowMapper<Book>(Book.class), 10);
  • 批量添加的方法:jdbcTemplate.batchUpdate(sql, list);
    • 核心代码
      @Override
      public void batchAdd(List<Object[]> list) {
          String sql = "insert into book (`name`, `status`,`created_at`) values (?,?,?)";
          int[] ints = jdbcTemplate.batchUpdate(sql, list);
          System.out.println(Arrays.toString(ints));
      }
      // 批量添加
      ArrayList<Object[]> list = new ArrayList<Object[]>();
      list.add(new Object[]{"Java", Book.STATUS_ON, time});
      list.add(new Object[]{"PHP", Book.STATUS_ON, time});
      bookService.batchAdd(list);
      
  • 批量删除、批量修改方法与批量添加一样,这里省略

事务

  • 分类:编程试事务、声明试事务
  • 编程试事务(传统try{}catch(){}方式,不推荐)
  • 声明试事务
    • 基于注解
      • 底层采用AOP原理,Spring提供事务API
      • Maven添加好需要的依赖(具体参考我的“Maven常用依赖”一文)
      • 配置开启事务
        • 开启注解扫描
        • 读取jdbc配置文件
        • 注册druid
        • 注册JdbcTemplate
        • 注册事务管理器
        • 开启事务注解
      • 创建dao、service,并添加好相关注解
        • @Transactional:开启事务(放在方法上该方法开启事务,放在类上类中所有方法都开启事务)
      • 核心代码
        <!-- 开启注解扫描 -->
        <context:annotation-config></context:annotation-config>
        <context:component-scan base-package="cn.cnyasin"/>
        <!-- 读取jdbc配置文件 -->
        <context:property-placeholder location="jdbc.properties"/>
        <!-- 注册druid -->
        <bean id="druid" class="com.alibaba.druid.pool.DruidDataSource">
            <property name="driverClassName" value="${jdbc.driverClassName}"/>
            <property name="url" value="${jdbc.url}"/>
            <property name="username" value="${jdbc.username}"/>
            <property name="password" value="${jdbc.password}"/>
        </bean>
        <!-- 注册JdbcTemplate -->
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
            <property name="dataSource" ref="druid"/>
        </bean>
        <!-- 注册事务管理器 -->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="druid"/>
        </bean>
        <!-- 开启事务注解 -->
        <tx:annotation-driven transaction-manager="transactionManager"/>
        
        public interface UserDao {
            // 减余额
            void reduceMoney(String username, Long money);
            // 加余额
            void addMoney(String username, Long money);
        }
        @Repository
        public class UserDaoImpl implements UserDao {
            @Autowired
            private JdbcTemplate jdbcTemplate;
            public void reduceMoney(String username, Long money) {
                String sql = "update user set balance = balance - ? where username = ?";
                Object[] args = {money, username};
                int update = jdbcTemplate.update(sql, args);
            }
            public void addMoney(String username, Long money) {
                String sql = "update user set balance = balance + ? where username = ?";
                Object[] args = {money, username};
                int update = jdbcTemplate.update(sql, args);
            }
        }
        @Service
        public class UserService {
            @Autowired
            private UserDaoImpl userDao;
            @Transactional // 开启事务(放在方法上该方法开启事务,放在类上类中所有方法都开启事务)
            public void gaveMoney() {
                String reduceUsername = "Jack";
                String addUsername = "Tom";
                Long money = 100L;
                // 减钱
                userDao.reduceMoney(reduceUsername, money);
                int i = 10 / 0;
                // 加钱
                userDao.addMoney(addUsername, money);
            }
        }
        
    • 基于xml
      • 配置开启事务
        • 开启注解扫描
        • 读取jdbc配置文件
        • 注册druid
        • 注册JdbcTemplate
        • 注册事务管理器
        • 配置通知
        • 配置切入点和切面
        • 删除Java代码层面的@Transactional注解
      • 其余操作参考上一部分基于注解
      • 核心代码
        <!-- 注册事务管理器 -->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="druid"/>
        </bean>
        <!-- 开启事务注解 -->
        <!--<tx:annotation-driven transaction-manager="transactionManager"/>-->
        <!-- 通过xml配置文件开启事务 -->
        <!-- 配置通知 -->
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
            <!-- 配置事务参数 -->
            <tx:attributes>
                <!-- 指定那种规则的方法加事务:支持模糊匹配 -->
                <tx:method name="gaveMoney0" propagation="REQUIRED"/>
                <!--<tx:method name="gave*"/>-->
            </tx:attributes>
        </tx:advice>
        <!-- 配置切入点和切面 -->
        <aop:config>
            <!-- 配置切入点 -->
            <aop:pointcut id="pt" expression="execution(* cn.cnyasin.service.UserService.*(..))"/>
            <!-- 配置切面 -->
            <aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/>
        </aop:config>
        
    • 基于完全注解
      • 创建配置类
      • 配置组件扫描
      • 开启事务
      • 创建bean方法返回数据库连接池
      • 创建bean方法返回JdbcTemplate
      • 创建bean方法返回事务管理器
      • 核心代码
        @Configuration // 配置类
        @ComponentScan("cn.cnyasin") // 组件扫描
        @EnableTransactionManagement // 开启事务
        public class TxConfig {
        
            // 创建数据库连接池
            @Bean
            public DruidDataSource getDruidDataSource() throws IOException {
        
                // 读取配置文件
                InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("jdbc.properties");
                Properties properties = new Properties();
                properties.load(resourceAsStream);
        
                DruidDataSource druidDataSource = new DruidDataSource();
                druidDataSource.setDriverClassName(properties.getProperty("jdbc.driverClassName"));
                druidDataSource.setUrl(properties.getProperty("jdbc.url"));
                druidDataSource.setUsername(properties.getProperty("jdbc.username"));
                druidDataSource.setPassword(properties.getProperty("jdbc.password"));
        
                return druidDataSource;
            }
        
            // 创建JdbcTemplate
            @Bean
            public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        
                JdbcTemplate jdbcTemplate = new JdbcTemplate();
                jdbcTemplate.setDataSource(dataSource);
        
                return jdbcTemplate;
            }
        
            // 创建事务管理器
            @Bean
            public DataSourceTransactionManager dataSourceTransactionManager(DataSource dataSource) {
        
                DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
                dataSourceTransactionManager.setDataSource(dataSource);
        
                return dataSourceTransactionManager;
            }
        }
        
  • 声明试事务的参数
    • propagation:传播行为(多事务进行调用时怎么管理),默认值:Propagation.REQUIRED
      • REQUIRED:当前方法有事务就在该事务中运行,没有事务则创建新事务后在新事务中运行(默认值,常用)
      • REQUIRES_NEW:创建新事务,如果原来有事务就挂起原来的,然后在新事务中运行(常用)
      • SUPPORTS:有事务就在该事务中运行,没有事务就非事务运行
      • NOT_SUPPORTED:非事务运行,如果有事务就挂起该事务后非事务运行
      • MANDATORY:有事务就在该事务中运行,没有事务就抛出异常
      • NEVER:非事务运行,如果有事务就抛出异常
      • NESTED:嵌套事务(注意:这个需要各大厂商的支持)
    • isolation:隔离级别(之前讲过了),默认值:Isolation.DEFAULT
    • timeout:超时时间,默认值:-1
    • readOnly:是否只读,默认值:false
      • 如果设置为true,则只能进行查询操作,无法执行增删改操作
    • rollbackFor:回滚,默认空对象,接受各种异常的class
      • 设置出现哪些异常时进行事务回滚
    • noRollbackFor:不回滚,默认空对象,接受各种异常的class
      • 设置出现哪些异常时不进行事务回滚
    • 核心代码
      @Transactional(
          propagation = Propagation.REQUIRED,
          isolation = Isolation.DEFAULT,
          timeout = -1,
          readOnly = false,
          rollbackFor = {},
          noRollbackFor = {}
      )
      

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值