Spring一:入门程序和增删改查

1 概述

简介

  1. Spring是分层的Java SE/EE应用full-stack(一站式)轻量级开源框架,以IoC(Inverse Of Control 反转控制)和AOP(Aspect Oriented Programming 面向切面编程)为内核,使用基本的Java Bean来完成以前只可能由EJB ( Enterprise Java Beans, Java企业Bean)完成的工作,取代了EJB的靡肿、低效的开发模式。

  2. Spring在表现层提供了SpringMVC与Struts框架的整合功能;在业务逻辑层可以管理事务、记录日志等;在持久层可以整合MyBatis、 Hibernate、JdbcTemplate等技术。因此,可以说Spring是企业应用开发很好的"一站式"选择。

  3. 优点

    1. 方便解耦、简化开发
    2. 支持AOP
    3. 支持声明式事务处理
    4. 方便程序的测试
    5. 方便集成各种优秀框架
    6. 降低JavaEE API的使用难度
    7. 非侵入式设计
  4. 体系结构

IoC & DI

  1. 耦合性

    1. 耦合性(Coupling),也叫耦合度,是对模块间关联程度的度量。耦合的强弱取决于模块间接口的复杂性、调用模块的方式以及通过界面传送数据的多少。模块间的耦合度是指模块之间的依赖关系,包括控制关系、调用关系、数据传递关系。模块间联系越多,其耦合性越强,同时表明其独立性越差( 降低耦合性,可以提高其独立性)。耦合性存在于各个领域,而非软件设计中独有的,但是我们只讨论软件工程中的耦合。
    2. 在软件工程中,耦合指的就是就是对象之间的依赖性。对象之间的耦合越高,维护成本越高。因此对象的设计应使类和构件之间的耦合最小。软件设计中通常用耦合度和内聚度作为衡量模块独立程度的标准。划分模块的一个准则就是高内聚低耦合。
    3. 耦合类型
      1. 内容耦合:当一个模块直接修改或操作另一个模块的数据时,或一个模块不通过正常入口而转入另一个模块时,这样的耦合被称为内容耦合。内容耦合是最高程度的耦合,应该避免使用。
      2. 公共耦合:两个或两个以上的模块共同引用一个全局数据项,这种耦合被称为公共耦合。
      3. 外部耦合:一组模块都访问同一全局简单变量而不是同一全局数据结构,而且不是通过参数表传递该全局变量的信息,则称之为外部耦合。
      4. 控制耦合:一个模块通过接口向另一个模块传递一个控制信号,接受信号的模块根据信号值而进行适当的动作,这种耦合被称为控制耦合。
      5. 标记耦合:若一个模块A通过接口向两个模块B和C传递一个公共参数,那么称模块B和C之间存在一个标记耦合。
      6. 数据耦合:模块之间通过参数来传递数据,那么被称为数据耦合。数据耦合是最低的一种耦合形式。
      7. 非直接耦合:两个模块之间没有直接关系,它们之间的联系完全是通过主模块的控制和调用来实现的。

    总结: 耦合是影响软件复杂程度和设计质量的一个重要因素,在设计上我们应采用以下原则:如果模块间必须存在耦合,就尽量使用数据耦合,少用控制耦合,限制公共耦合的范围,尽量避免使用内容耦合。

  2. 内聚性

    1. 内聚标志一个模块内各个元素彼此结合的紧密程度,它是信息隐蔽和局部化概念的自然扩展。内聚是从功能角度来度量模块内的联系,一个好的内聚模块应当恰好做一件事。
    2. 内聚描述的是模块内的功能联系,耦合是模块之间的联系。
    3. 程序讲究的是低耦合,高内聚。就是同一个模块内的各个元素之间要高度紧密,但是各个模块之间的相互依存度却要不那么紧密。
    4. 内聚和耦合是密切相关的,同其他模块存在高耦合的模块意味着低内聚,而高内聚的模块意味着该模块同其他模块之间是低耦合。在进行软件设计时,应力争做到高内聚,低耦合。
  3. 可以使用工厂模式解耦。

  4. 控制反转(IoC)作用:它不能实现数据库的增删改查,也不能实现表现层的请求参数的封装,甚至也无法接收请求,能干的事情只有一件,即降低程序间的耦合(依赖关系)。注:是降低(用到工厂模式,工程模式用到反射),不能消除。

xml 和 annotation 对比

  1. 见下表

    • xml优点:修改时,不用改源码,不涉及重新编译和部署;annotation优势:配置简单,维护方便。
    对比项xmlannotation
    Bean的定义<bean id="" class=""/>@Component,衍生物@Controller @Service @Repository
    Bean的名称通过id或name指定@Component(“user”)
    Bean的注入<property>属性(即set注入,最常用)@Autowired按类型注入 ; @Qualifier按名称注入
    生命周期init-method、destroy-method@PostConstruct初始化、@PreDestroy销毁
    Bean作用范围scope属性@Scope
    适用场景Bean来自第三方,使用它Bean的实现类由用户自己开发
  2. 常用注解

    分类注解说明xml 方式
    创建对象@Component
    @Controller
    @Service
    @Repository
    把资源让spring来管理,即在xml中配置一个bean<bean id="" class=""/>
    注入数据@Autowired
    @Qualifier
    @Resource
    @Value
    前三个用于注入 bean,第四个用于注入值<property name="" ref=""/>
    <property name="" value=""/>
    作用域@Scope指定bean的作用范围<bean id="" class="" scope=""/>
    生命周期@PostConstruct
    @PreDestroy
    用于指定初始化/销毁的方法<bean id="" class="" init-method="" destroy-method=""/>
    新注解@Configuration用于指定当前类是一个spring配置类,相当于代替了bean.xml
    @ComponentScan用于指定spring在初始化容器时要扫描的包<context:component-scanbase-package="" />
    @Bean该注解只能写在方法上,表明使用此方法创建一个对象,并且放入spring容器
    @PropertySource用于加载 .properties 文件中的配置
    @Import用于导入其他配置类,在引入其他配置类时,可以不用再写@Configuration注解(当然写上也没问题)

2 入门程序

2.1 xml方式

  • 创建普通 maven 工程即可,项目整体结构如下

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-naOLsfOJ-1638512809119)(assets/image-20211116213609325.png)]

  1. 依赖

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.18.RELEASE</version>
    </dependency>
    
  2. 业务层

    package cn.service;
    
    public interface UserService {
        void say();
    }
    
    package cn.service.impl;
    
    import cn.service.UserService;
    
    public class UserServiceImpl implements UserService {
        @Override
        public void say() {
            System.out.println("Hello Spring ! 我用xml方式入门了!");
        }
    }
    
  3. application.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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans.xsd">
        <bean id="userService" class="cn.service.impl.UserServiceImpl"/>
    </beans>
    
  4. 运行

    package cn;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import cn.service.UserService;
    
    public class App {
        public static void main(String[] args) {
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
            UserService service = (UserService) applicationContext.getBean("userService");
            service.say();
            /*
             * 结果
             * Hello Spring ! 我用xml方式入门了!
             */
        }
    }
    

2.2 annotation方式

  • 普通maven工程,项目结构如下

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rJKcqUYB-1638512809120)(assets/image-20211116213813349.png)]

  1. 依赖

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.18.RELEASE</version>
    </dependency>
    
  2. 业务层

    package cn.service;
    
    public interface UserService {
        void say();
    }
    
    package cn.service.impl;
    
    import cn.service.UserService;
    import org.springframework.stereotype.Component;
    
    @Component("userService")
    public class UserServiceImpl implements UserService {
        @Override
        public void say() {
            System.out.println("Hello Spring ! 我用annotation方式入门了!");
        }
    }
    
  3. 配置类

    package cn.conf;
    
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    @ComponentScan("cn.service")
    public class SpringConf {
    }
    
  4. 运行

    package cn;
    
    import cn.conf.SpringConf;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import cn.service.UserService;
    
    public class App {
        public static void main(String[] args) {
            ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConf.class);
            UserService service = (UserService) applicationContext.getBean("userService");
            service.say();
            /**
             * 结果
             * Hello Spring ! 我用annotation方式入门了!
             */
        }
    }
    

3 增删改查

SQL脚本

create table account(
	id int primary key auto_increment,
	name varchar(40),
	money double
)character set utf8 collate utf8_general_ci;

insert into account(name,money) values('张三',500.0);
insert into account(name,money) values('李四',1000.0);
insert into account(name,money) values('王五',2000.0);

3.1 xml方式

  • 普通maven工程,结构图如下

    在这里插入图片描述

  1. 依赖

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.18.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.2.18.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.21</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.22</version>
    </dependency>
    
  2. 实体类

    package cn.pojo;
    
    import lombok.Data;
    
    @Data
    public class Account {
        private Integer id;
        private String name;
        private Double money;
    }
    
  3. 持久层

    package cn.dao;
    
    import cn.pojo.Account;
    
    import java.util.List;
    
    public interface AccountDao {
        // 返回受影响的行数
        Integer addAccount(Account account);
    
        Integer deleteAccount(Integer id);
    
        Integer updateAccount(Account account);
    
        Account findAccountById(Integer id);
    
        List<Account> findAll();
    }
    
    package cn.dao.impl;
    
    
    import cn.dao.AccountDao;
    import cn.pojo.Account;
    import org.springframework.jdbc.core.BeanPropertyRowMapper;
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.jdbc.core.RowMapper;
    
    import java.util.List;
    
    public class AccountDaoImpl implements AccountDao {
        /**
         * 定义JdbcTemplate属性并实现其set方法(依赖注入时使用)
         */
        private JdbcTemplate jdbcTemplate;
    
        public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
            this.jdbcTemplate = jdbcTemplate;
        }
    
        /**
         * 增删改全用 update 方法
         */
        public Integer addAccount(Account account) {
            String sql = "insert into account(name,money) values (?,?) ";
            Object[] obj = new Object[]{account.getName(), account.getMoney()};
            int num = jdbcTemplate.update(sql, obj);
            return num;
        }
    
        public Integer deleteAccount(Integer id) {
            String sql = "delete from account where id=? ";
            Integer num = jdbcTemplate.update(sql, id);
            return num;
        }
    
        public Integer updateAccount(Account account) {
            String sql = "update account set name=? , money=? where id=? ";
            Object[] params = new Object[]{account.getName(), account.getMoney(), account.getId()};
            Integer num = jdbcTemplate.update(sql, params);
            return num;
        }
    
        public Account findAccountById(Integer id) {
            String sql = "select * from account where id=? ";
            RowMapper<Account> rowMapper = new BeanPropertyRowMapper<Account>(Account.class);
            return jdbcTemplate.queryForObject(sql, rowMapper, id);
        }
    
        public List<Account> findAll() {
            String sql = "select * from account ";
            RowMapper<Account> rowMapper = new BeanPropertyRowMapper<Account>(Account.class);
            return jdbcTemplate.query(sql, rowMapper);
        }
    }
    
  4. 配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
                    http://www.springframework.org/schema/beans/spring-beans.xsd">
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://192.168.181.160:3306/test?serverTimezone=CTT"/>
            <property name="username" value="root"/>
            <property name="password" value="root"/>
        </bean>
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
            <property name="dataSource" ref="dataSource"/>
        </bean>
    
        <bean id="accountDao" class="cn.dao.impl.AccountDaoImpl">
            <property name="jdbcTemplate" ref="jdbcTemplate"/>
        </bean>
    </beans>
    
  5. 测试类

    package cn.dao;
    
    import cn.pojo.Account;
    import org.junit.Before;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import java.util.List;
    
    public class AccountDaoTest {
    
    
        private AccountDao accountDao;
    
        @Before
        public void init() {
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
            accountDao = (AccountDao) applicationContext.getBean("accountDao");
        }
    
    
        @Test
        public void addAccount() {
            Account account = new Account();
            account.setName("孙悟空");
            account.setMoney(666.6);
            Integer num = accountDao.addAccount(account);
            if (num > 0) {
                System.out.println("添加成功");
            } else {
                System.out.println("添加失败");
            }
        }
    
        @Test
        public void deleteAccount() {
            Integer num = accountDao.deleteAccount(4);
            if (num > 0) {
                System.out.println("删除成功");
            } else {
                System.out.println("删除失败");
            }
        }
    
        @Test
        public void updateAccount() {
            Account account = new Account();
            account.setName("李小四");
            account.setMoney(500.0);
            account.setId(2);
            Integer num = accountDao.updateAccount(account);
            if (num > 0) {
                System.out.println("更新成功");
            } else {
                System.out.println("更新失败");
            }
        }
    
        @Test
        public void findAccountById() {
            Account account = accountDao.findAccountById(1);
            System.out.println(account);
        }
    
        @Test
        public void findAll() {
            List<Account> accounts = accountDao.findAll();
            accounts.forEach(account -> System.out.println(account));
        }
    }
    

3.2 annotation方式

  • 普通maven工程,结构图如下

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KGLwkYC9-1638512809121)(assets/image-20211116214733356.png)]

  1. 依赖

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.18.RELEASE</version>
    </dependency>
    <!-- druid 连接池,上面xml方法用的spring-jdbc -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.2.8</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.21</version>
    </dependency>
    <dependency>
        <groupId>commons-dbutils</groupId>
        <artifactId>commons-dbutils</artifactId>
        <version>1.4</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>5.2.18.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.22</version>
    </dependency>
    
  2. 实体类

    package cn.pojo;
    
    import lombok.Data;
    
    @Data
    public class Account {
        private Integer id;
        private String name;
        private Double money;
    }
    
  3. 持久层

    package cn.dao;
    
    import cn.pojo.Account;
    
    import java.util.List;
    
    public interface AccountDao {
        void addAccount(Account account);
    
        void deleteAccount(Integer id);
    
        void updateAccount(Account account);
    
        Account findAccountById(Integer id);
    
        List<Account> findAll();
    }
    
    package cn.dao.impl;
    
    import cn.dao.AccountDao;
    import cn.pojo.Account;
    import org.apache.commons.dbutils.QueryRunner;
    import org.apache.commons.dbutils.handlers.BeanHandler;
    import org.apache.commons.dbutils.handlers.BeanListHandler;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Repository;
    
    import java.util.List;
    
    @Repository
    public class AccountDaoImpl implements AccountDao {
        @Autowired
        private QueryRunner runner;
    
        /**
         * 增删改全用QueryRunner的update方法
         * xml中的 jdbtTemplate类似,也是增删改全用update
         */
        public void addAccount(Account account) {
            try {
                String sql = " insert into account(name,money) values (?,?) ";
                runner.update(sql, account.getName(), account.getMoney());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
    
        }
    
        public void deleteAccount(Integer id) {
            try {
                String sql = " delete from account where id=? ";
                runner.update(sql, id);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        public void updateAccount(Account account) {
            try {
                String sql = " update account set name=? , money=? where id=? ";
                runner.update(sql, account.getName(), account.getMoney(), account.getId());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        public Account findAccountById(Integer id) {
            try {
                String sql = " select * from account where id=? ";
                // 类似于JdbcTemplate中的RowMapper
                BeanHandler<Account> beanHandler = new BeanHandler<Account>(Account.class);
                return runner.query(sql, beanHandler, id);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        public List<Account> findAll() {
            try {
                String sql = " select * from account ";
                BeanListHandler<Account> beanListHandler = new BeanListHandler<Account>(Account.class);
                return runner.query(sql, beanListHandler);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
    
  4. 配置

    # 数据源配置文件内容
    # 路径:resources/dataSource.properties
    datasource.driver=com.mysql.cj.jdbc.Driver
    datasource.url=jdbc:mysql://192.168.181.160:3306/test?serverTimezone=CTT
    datasource.username=root
    datasource.password=root
    
    package cn.conf;
    
    import com.alibaba.druid.pool.DruidDataSource;
    import org.apache.commons.dbutils.QueryRunner;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Scope;
    
    import javax.sql.DataSource;
    
    public class DataSourceConf {
        @Value("${datasource.driver}")
        private String driver;
        @Value("${datasource.url}")
        private String url;
        @Value("${datasource.username}")
        private String username;
        @Value("${datasource.password}")
        private String password;
    
        // @Bean:创建一个对象,并且放入spring容器
        @Bean(name = "runner")
        @Scope("prototype")
        public QueryRunner createQueryRunner(@Qualifier("ds") DataSource dataSource) {
            return new QueryRunner(dataSource);
        }
    
        @Bean(name = "ds")
        public DataSource createDataSource() {
            try {
                DruidDataSource druidDataSource = new DruidDataSource();
                druidDataSource.setDriverClassName(driver);
                druidDataSource.setUrl(url);
                druidDataSource.setUsername(username);
                druidDataSource.setPassword(password);
                return druidDataSource;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
    
    package cn.conf;
    
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Import;
    import org.springframework.context.annotation.PropertySource;
    
    @Configuration
    @ComponentScan("cn.dao")
    @PropertySource("classpath:dataSource.properties")
    @Import(DataSourceConf.class)
    public class SpringConf {
    
    }
    
  5. 测试

    package cn.dao;
    
    import cn.conf.SpringConf;
    import cn.pojo.Account;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import java.util.List;
    
    // 这俩注解在spring-test依赖中
    // @RunWith(SpringJUnit4ClassRunner.class)替换原有运行器(即Spring整合junit)
    // @ContextConfiguration(classes = SpringConfig.class)指定spring配置类
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = SpringConf.class)
    public class AccountDaoTest {
    
        @Autowired
        private AccountDao accountDao;
    
        @Test
        public void addAccount() {
            Account account = new Account();
            account.setName("lkf");
            account.setMoney(2000.5);
            accountDao.addAccount(account);
        }
    
        @Test
        public void deleteAccount() {
            accountDao.deleteAccount(6);
        }
    
        @Test
        public void updateAccount() {
            Account account = new Account();
            account.setName("张小三");
            account.setMoney(500.0);
            account.setId(1);
            accountDao.updateAccount(account);
        }
    
        @Test
        public void findAccountById() {
            Account account = accountDao.findAccountById(1);
            System.out.println(account);
        }
    
        @Test
        public void findAll() {
            List<Account> accounts = accountDao.findAll();
            accounts.forEach(account -> System.out.println(account));
        }
    }
    
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值