• Spring - IOC注解开发


    Spring_IOC注解开发

    一、基于注解的IOC和DI

    1. 快速入门(重点)

    需求描述
    • 有dao层:UserDaoUserDaoImpl
    • 有service层:UserServiceUserServiceImpl
    • 使用注解配置bean,并注入依赖
    需求分析
    1. 准备工作:创建Maven项目,导入依赖坐标

    2. 编写代码并注解配置:

      编写dao层、service层代码,使用注解@Component配置bean:代替xml里的bean标签

      使用注解@Autowired依赖注入:代替xml里的propertyconstructor-arg标签

    3. 在xml配置文件中开启组件扫描

    4. 测试

    需求实现
    1) 准备工作
    • 创建Maven项目,导入依赖坐标
        <dependencies>
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-contextartifactId>
                <version>5.1.2.RELEASEversion>
            dependency>
            <dependency>
                <groupId>junitgroupId>
                <artifactId>junitartifactId>
                <version>4.12version>
            dependency>
        dependencies>
    
    2) 编写代码,并注解配置
    • UserDao接口
    package com.itheima.dao;
    
    public interface UserDao {
        void add();
    }
    
    • UserDaoImpl实现类
    package com.itheima.dao.impl;
    
    import com.itheima.dao.UserDao;
    import org.springframework.stereotype.Component;
    import org.springframework.stereotype.Repository;
    
    @Component
    public class UserDaoImpl implements UserDao {
        public void add() {
            System.out.println("调用了UserDaoImpl的add方法~!~");
        }
    }
    
    
    
    • UserService接口
    package com.itheima.service;
    
    public interface UserService {
        void add();
    }
    
    
    • UserServiceImpl实现类
    package com.itheima.service.impl;
    
    import com.itheima.dao.UserDao;
    import com.itheima.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Scope;
    import org.springframework.stereotype.Component;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.PostConstruct;
    import javax.annotation.PreDestroy;
    
    /*
        需求:
            在UserServiceImpl里面调用UserDaoImpl的add方法
        分析:
            1. 把这两个类交给spring管理,让spring创建这两个类的对象
            2. 在UserServiceImpl里面注入UserDaoImpl 的对象
            3. 使用对象来调用方法
         步骤:
            1. 在UserServiceImpl和UserDaoImpl身上打注解 :  @Component
            2. 在UserServiceImpl里面定义属性,private UserDao userDao;
            3. 在属性身上打注解:  @AutoWired
            4. 在xml里面打开扫描的开关,这样spring才能知道哪些类要创建对象,里面的什么属性要注入!
     */
    @Component 
    public class UserServiceImpl implements UserService {
    
        @Autowired
        private UserDao userDaoImpl;  //被注入的属性写成 接口 类型比较好,后面的属性名可以改成接口的任一实现类,因为实现类的bean 的id 默认是首字母小写的类名。接口有多个实现类就会有属性名去找默认id是属性名的bean
    
        public void add() {
            System.out.println("调用了UserServiceImpl的add方法~!");
            userDaoImpl.add();
        }
    
    }
    
    
    3) 开启组件扫描
    • 创建applicationContext.xml,注意引入的context名称空间
    
    <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"
           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">
    
    
        
        
        <context:component-scan base-package="com.itheima"/>
    beans>
    
    4) 功能测试
    • 创建一个测试类,调用Service
    package com.itheima.test;
    
    import com.itheima.service.UserService;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class TestUserServiceImpl {
    
        @Test
        public void testAdd(){
    
            //1. 创建工厂
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    
            //2. 问工厂要对象
            UserService us = context.getBean(UserService.class);
    
            //3. 调用方法
            us.add();
    
        }
    }
    
    
    步骤小结
    1. 导入依赖

    2. 定义接口和实现类(dao 和 service)

    3. 在实现类上面打上注解 @Component

    4. 在属性上面打上注解@AutoWired

    5. 在applicationContext.xml里面打开扫描的开关

    2. 注解使用详解

    2.1 开启组件扫描
    • 在Spring中,如果要使用注解开发,就需要在applicationContext.xml中开启组件扫描,配置如下:
    
    <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"
           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">
    
    
        
        
        <context:component-scan base-package="com.itheima"/>
    beans>
    
    2.2 声明bean的注解【IOC】
    简介
    注解说明
    @Component用在类上,相当于bean标签
    @Controller用在web层类上,配置一个bean(是@Component的衍生注解)
    @Service用在service层类上,配置一个bean(是@Component的衍生注解)
    @Repository用在dao层类上,配置一个bean(是@Component的衍生注解)
    • @Component:类级别的一个注解,用于声明一个bean,使用不多
      • value属性:bean的唯一标识 (id值)。如果不配置,默认以首字母小写的类名为id
    • @Controller, @Service, @Repository,作用和@Component完全一样,但更加的语义化,使用更多
      • @Controller:用于web层的bean
      • @Service:用于Service层的bean
      • @Repository:用于dao层的bean
    示例
    • UserDaoImpl类上使用注解@Repository
    @Repository("userDao")
    public class UserDaoImpl implements UserDao{
    }
    
    • UserServiceImpl类上使用注解@Service
    @Service("userService")
    public class UserServiceImpl implements UserService{
    }
    
    • UserController类上使用注解@Controller
    @Controller
    public class UserController{}
    
    2.3 配置bean的注解 【IOC】
    注解说明
    @Scope相当于bean标签的scope属性
    @PostConstruct相当于bean标签的init-method属性
    @PreDestroy相当于bean标签的destory-method属性
    配置bean的作用范围:
    • @Scope:配置bean的作用范围,相当于bean标签的scope属性。加在bean对象上

    • @Scope的常用值有:

    • singleton:单例的,容器中只有一个该bean对象

      • 何时创建:容器初始化时
      • 何时销毁:容器关闭时
    • prototype:多例的,每次获取该bean时,都会创建一个bean对象

      • 何时创建:获取bean对象时
      • 何时销毁:长时间不使用,垃圾回收
    @Scope("prototype")
    @Service("userService")
    public class UserServiceImpl implements UserService{
        //...
    }
    
    配置bean生命周期的方法
    • @PostConstruct是方法级别的注解,用于指定bean的初始化方法
    • @PreDestroy是方法级别的注解,用于指定bean的销毁方法
    package com.itheima.service.impl;
    
    import com.itheima.dao.UserDao;
    import com.itheima.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Scope;
    import org.springframework.stereotype.Component;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.PostConstruct;
    import javax.annotation.PreDestroy;
    
    /*
        需求:
            在UserServiceImpl里面调用UserDaoImpl的add方法
        分析:
            1. 把这两个类交给spring管理,让spring创建这两个类的对象
            2. 在UserServiceImpl里面注入UserDaoImpl 的对象
            3. 使用对象来调用方法
         步骤:
            1. 在UserServiceImpl和UserDaoImpl身上打注解 :  @Component
            2. 在UserServiceImpl里面定义属性,private UserDao userDao;
            3. 在属性身上打注解:  @AutoWired
            4. 在xml里面打开扫描的开关,这样spring才能知道哪些类要创建对象,里面的什么属性要注入!
     */
    
    
    /*
        IOC的注解:
            @Component : 是通用的注解
                @Controller :针对web层
                @Service : 针对service层
                @Repository :针对dao层
    
                属性:
                    value :  用来指定id值,如果不指定,那么将会把类名(首字母小写)作为id值!
    
            @Scope: 用来配置单例或者多例
                singleton: 单例, 默认就是单例
                prototype: 多例
            @PostConstruct: 创建对象的时候,调用指定的方法
            @PreDestroy: 销毁对象的时候调用指定的方法
    
     */
    //@Component //组件
    @Service("us")
    @Scope("prototype")
    public class UserServiceImpl implements UserService {
    
        @Autowired
        private UserDao userDaoImpl;
    
        public void add() {
            System.out.println("调用了UserServiceImpl的add方法~!");
            userDaoImpl.add();
        }
    
        //=========================================
        //对象创建完毕,就执行这个方法
        @PostConstruct
        public void init(){
            System.out.println("调用了UserServiceImpl的init方法~!");
        }
    
        //对象销毁的时候,就执行这个方法! 只有单例才会走这个方法
        @PreDestroy
        public void destroy(){
            System.out.println("调用了UserServiceImpl的destroy方法~!");
        }
    }
    
    
    2.4 依赖注入的注解【DI】
    注解说明
    @Autowired相当于property标签的ref 注入对象
    @Qualifier结合@Autowired使用,用于根据名称(标识符)注入依赖
    @Resource相当于@Autowired + @Qualifier
    @Value相当于property标签的value ,注入普通 的属性
    注入bean对象
    • @Autowired:用于byType(按照类型来找对象)注入bean对象,按照依赖(属性)的类型,从Spring容器中查找要注入的bean对象
        1. 如果找到一个,直接注入
        1. 如果找到多个,则以变量名为id,查找bean对象并注入
          1. 如果找不到,抛异常
    • @Qualifier:是按id注入,但需要和@Autowired配合使用。
    • @Resource:(是jdk提供的)用于注入bean对象(byName注入),相当于@Autowired + @Qualifier

    绝大多数情况下,只要使用@Autowired注解注入即可

    使用注解注入时,不需要set方法了

    • UserDao
    package com.itehima.dao;
    
    public interface UserDao {
        void add();
    }
    
    • UserDao实现
    package com.itheima.dao.impl;
    
    import com.itheima.dao.UserDao;
    import org.springframework.stereotype.Component;
    
    @Repository
    public class UserDaoImpl implements UserDao {
        public void add() {
            System.out.println("调用了UserdaoImpl的add方法~!~");
        }
    }
    
    
    • UserService
    package com.itehima.service;
    
    public interface UserService {
        void add();
    }
    
    • UserService实现
    package com.itheima.service.impl;
    
    import com.itheima.dao.UserDao;
    import com.itheima.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Scope;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.PostConstruct;
    import javax.annotation.PreDestroy;
    import javax.annotation.Resource;
    
    @Service("us02")
    public class UserServiceImpl02 implements UserService {
    
        /*
    
            @Autowired :自动注入
                1. 按照的属性类型去找spring的工厂里面找对象,找到对象(只有一个)就注入进来
                2. 如果在spring的工厂里面,有多个对象满足这种类型,
                    2.1 会拿着属性的名字当成id ,再去找对象,如果有匹配的就注入。
                    2.2 如果还没有找到匹配的,就会报错!
            @Qualifier : 用于给@Autowired指定id值。告诉它用这个id去找对象注入
            @Resource :  等价于@Autowired + @Qualifier
                1. 按照id去找对象注入
    
             以上三个注解,就是用注入对象的,最常用的是@Autowired,而且95%的场景下,是只有一种实现类\
    
             @Value : 用来注入普通的数据
                1. 主要是用来注入properties里面的数据
                2. @Value("${properties里面的KEY}") , 要先导入进来properties的文件才可以注入
         */
        @Autowired
        private UserDao userDaoImpl02;
    
        @Autowired
        @Qualifier("userDaoImpl02")
        private UserDao abc;
    
        @Resource(name = "userDaoImpl02")
        private UserDao cba;
    
        @Value("深圳")
        private String address;
    
        public void add() {
            System.out.println("调用了UserServiceImpl02的add方法~!" + address);
            //userDaoImpl02.add();
            //abc.add();
            cba.add();
        }
    }
    
    
    
    • 测试
    package com.itheima.test;
    
    import com.itheima.service.UserService;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class TestUserServiceImpl02 {
    
        @Test
        public void testAdd(){
    
            //1. 创建工厂
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    
            //2. 问工厂要对象
            UserService us = (UserService) context.getBean("us02");
    
    
            //3. 调用方法
            us.add();
    
        }
    }
    
    
    
    注入普通值
    • @Value:注入简单类型值,例如:基本数据类型和String
    @Service
    public class UserServiceImpl02 implements UserService{
        
        @Value("深圳")
        private String address;
        
        //...
    }
    
    小结
    • 在xml里要开启组件扫描
    <context:component-scan base-package="com.itheima"/>
    
    • 声明bean的注解(注册bean的注解) | IOC的注解
      • @Component("bean的名称"), 括号里面bean的名称就是id 值, 可以用在任何类上,注册bean对象
      • @Controller("bean名称"), @Service("bean名称"), @Repository("bean名称"),分别用于web层、service层、dao层的类上
    • 配置bean的注解
      • 如果要给一个bean设置作用范围:在bean上加注解@Scope("singleton/prototype")
      • 如果要给一个bean设置一个初始化方法:就在方法上加注解@PostConstruct
      • 如果要给一个bean设置一个销毁方法:就在方法上加注解@PreDestroy
    • 依赖注入的注解
      • @Autowired:byType注入,直接加在依赖项那个成员变量上
        • Spring会根据类型,从容器里查找bean并注入进来
        • 如果只找到一
        • 合的就会报错
      • @Autowired + @Qualifier("要注入的bean的名称"): 这种组合一般不怎么用,因为比较麻烦。
      • @Resource(name="要注入的bean的名称"):byName注入
      • @Value("要注入的简单值"):用于注入简单值
        • @Value("${properties里的key}"):把properties里指定key的值注入进来。前提条件是必须已经引入了properties文件

    二、整合Mybatis

    ​ spring作为service层框架,对dao层和web层提供了很好的支持,整合Mybatis其实就是把mybatis的核心配置文件(SQLMapConfig.xml) 给去掉,并且把调用mybatis的代码简化,简化成注入对象,然后直接调用方法。

    1. 导入依赖

    <dependencies>
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-contextartifactId>
                <version>5.1.2.RELEASEversion>
            dependency>
    
            <dependency>
                <groupId>junitgroupId>
                <artifactId>junitartifactId>
                <version>4.12version>
                <scope>testscope>
            dependency>
    
            
            
            
            
            
            
            <dependency>
                <groupId>com.mchangegroupId>
                <artifactId>c3p0artifactId>
                <version>0.9.5.4version>
            dependency>
    
    
            
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-jdbcartifactId>
                <version>5.1.2.RELEASEversion>
            dependency>
            
            <dependency>
                <groupId>org.mybatisgroupId>
                <artifactId>mybatis-springartifactId>
                <version>2.0.5version>
            dependency>
    
            <dependency>
                <groupId>org.mybatisgroupId>
                <artifactId>mybatisartifactId>
                <version>3.5.5version>
            dependency>
            
            <dependency>
                <groupId>mysqlgroupId>
                <artifactId>mysql-connector-javaartifactId>
                <version>5.1.32version>
            dependency>
    
            
            <dependency>
                <groupId>org.slf4jgroupId>
                <artifactId>slf4j-apiartifactId>
                <version>1.7.20version>
            dependency>
            
            <dependency>
                <groupId>ch.qos.logbackgroupId>
                <artifactId>logback-classicartifactId>
                <version>1.2.3version>
            dependency>
            
            <dependency>
                <groupId>ch.qos.logbackgroupId>
                <artifactId>logback-coreartifactId>
                <version>1.2.3version>
            dependency>
    
        dependencies>
    

    2. 定义dao接口和映射文件

    • 接口
    package com.itheima.dao;
    
    import com.itheima.bean.Brand;
    import org.springframework.stereotype.Repository;
    
    import java.util.List;
    
    
    public interface BrandDao {
    
        List<Brand> findAll();
    
    }
    
    
    • 映射文件
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.itheima.dao.BrandDao">
    
        <resultMap id="brandMap" type="Brand">
            <result column="brand_name" property="brandName"/>
            <result column="company_name" property="companyName"/>
        </resultMap>
    
        <select id="findAll"  resultMap="brandMap">
            select * from tb_brand
        </select>
    </mapper>
    

    3. 定义service接口和实现

    • 接口
    package com.itheima.service;
    
    import com.itheima.bean.Brand;
    
    import java.util.List;
    
    public interface BrandService {
    
        /**
         * 查询所有
         * @return
         */
        List<Brand> findAll();
    }
    
    
    • 实现
    package com.itheima.service.impl;
    
    import com.itheima.bean.Brand;
    import com.itheima.dao.BrandDao;
    import com.itheima.service.BrandService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    
    /*
        需求:
            在service里面调用dao的findAll方法。
        步骤:
            1. 不写mybatis的核心配置文件了,但是核心配置文件的内容还是需要有的。由spring来接管这个工作。
            2.  mybatis的核心配置文件里面包含两个部分的内容: 环境配置和映射文件配置
                2.1 环境配置由 SqlSessionFactoryBean类来接管
                2.2 映射文件配置由MapperScannerConfigure类来接管
            3. 以上的两个类需要在applicationContext.xml中定义出来!
    
            4. 在service类上打注解: @Service
            5. 在service里面定义出来dao的属性,然后在属性上打注解 : @Autowired
     */
    @Service
    public class BrandServiceImpl implements BrandService {
    
        @Autowired
        private BrandDao brandDao;
    
        @Override
        public List<Brand> findAll() {
            System.out.println("调用了BrandServiceImpl的findAll方法~!");
            return brandDao.findAll();
        }
    }
    

    4. 定义配置文件

    • db.properties
    db.driverClass=com.mysql.jdbc.Driver
    db.jdbcUrl=jdbc:mysql://localhost:3306/day29_demo
    db.user=root
    db.password=root
    
    • applicationContext.xml
    
    <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"
           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">
    
    
        
        <context:component-scan base-package="com.itheima"/>
    
        
    
        
        <context:property-placeholder location="db.properties"/>
    
        
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="driverClass" value="${db.driverClass}"/>
            <property name="jdbcUrl" value="${db.jdbcUrl}"/>
            <property name="user" value="${db.user}"/>
            <property name="password" value="${db.password}"/>
        bean>
    
        
        <bean class="org.mybatis.spring.SqlSessionFactoryBean">
            
            <property name="dataSource" ref="dataSource"/>
    
            
            <property name="typeAliasesPackage" value="com.itheima.bean"/>
        bean>
    
        
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="basePackage" value="com.itheima.dao"/>
        bean>
    
    beans>
    

    5. 单元测试

    package com.itheima.test;
    
    import com.itheima.service.BrandService;
    import com.itheima.service.impl.BrandServiceImpl;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class TestBrandServiceImpl {
    
        @Test
        public void testFindAll(){
    
            //1. 创建工厂
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    
            //2. 问工厂要对象
            BrandService bs = context.getBean(BrandServiceImpl.class);
    
            //3. 调用方法
            System.out.println(bs.findAll());
        }
    }
    

    三、纯注解开发IOC和DI

    ​ 在上边的CURD练习中,仍然有部分配置需要使用applicationContext.xml,那么能不能使用注解替换掉所有的xml呢?Spring提供了一些新注解,可以达到这个目标。

    请注意:Spring提供的这部分新注解,并非为了完全代替掉XML,只是提供了另外一种配置方案

    注解简介

    注解说明
    @Configuration被此注解标记的类,是配置类 等同于applicationContext.xml
    @ComponentScan用在配置类上,开启注解扫描。使用basePackage属性(等效于value属性,所以直接写包名也行)指定扫描的包
    @PropertySource用在配置类上,加载properties文件。使用value属性指定properties文件路径
    @Import用在配置类上,引入子配置类。用value属性指定子配置类的Class
    @Bean用在配置类的方法上,把返回值声明为一个bean。用name/value属性指定bean的id

    注解详解

    • 导入依赖
    <dependencies>
            
            <dependency>
                <groupId>com.mchangegroupId>
                <artifactId>c3p0artifactId>
                <version>0.9.5.2version>
            dependency>
            
            <dependency>
                <groupId>commons-dbutilsgroupId>
                <artifactId>commons-dbutilsartifactId>
                <version>1.7version>
            dependency>
            
            <dependency>
                <groupId>mysqlgroupId>
                <artifactId>mysql-connector-javaartifactId>
                <version>5.1.47version>
            dependency>
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-contextartifactId>
                <version>5.1.2.RELEASEversion>
            dependency>
            <dependency>
                <groupId>junitgroupId>
                <artifactId>junitartifactId>
                <version>4.12version>
            dependency>
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-testartifactId>
                <version>5.1.2.RELEASEversion>
            dependency>
        dependencies>
    
    1 @Configuration配置类
    • @Configuration把一个Java类声明为核心配置类
      • 加上Java类上,这个Java类就成为了Spring的核心配置类,用于代替applicationContext.xml
      • @Component的衍生注解,所以:核心配置类也是bean,也会被spring管理起来,当然里边也可以注入依赖
    /*
        @Configuration:
            1. 表示这个类是一个核心配置类
            2. 它的作用等价于以前的applicationContext.xml
            3. @Configuration 是从@Component注解衍生出来的,所以这个类也会被spring管理起来(创建对象)
     */
    @Configuration
    public class AppConfig {
    }
    
    2 配置类上的注解
    • @ComponentScan配置组件注解扫描

      • basePackages或者value属性:指定扫描的基本包
      • 等同于替代了applicationContext.xml里面的这句话
      
       <context:component-scan base-package="com.itheima"/>
      
    • @PropertySource用于加载properties文件

      • value属性:指定propertis文件的路径,从类加载路径里加载
      • 等同于替代了applicationContext.xml里面的这句话
      
      <context:property-placeholder location="classpath:db.properties"/>
      
    • @Import用于导入其它配置类

      • Spring允许提供多个配置类(模块化配置),在核心配置类里加载其它配置类
      • 相当于xml中的标签
    • 核心配置类

    package com.itheima.config;
    
    import com.mchange.v2.c3p0.ComboPooledDataSource;
    import org.apache.commons.dbutils.QueryRunner;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.*;
    import org.springframework.stereotype.Component;
    
    import javax.annotation.Resource;
    import javax.sql.DataSource;
    import java.beans.PropertyVetoException;
    
    /*
        @Configuration:
            1. 表示这个类是一个核心配置类
            2. 它的作用等价于以前的applicationContext.xml
            3. @Configuration 是从@Component注解衍生出来的,所以这个类也会被spring管理起来(创建对象)
        @ComponentScan :
            1. 用来指定扫描包,等价于 
        @PropertyScource:
            1. 用来导入外部的properties文件,等价于
            2. 导入这个properties文件的时候,如果有错(1. 找不到这个文件,2.这个文件无法打开,)可以在
                名字的前面加上 classpath:
            3. 要想把properties里面的内容注入进来,就需要定义好对应的属性,然后使用@Value来注入值
                @Value("${KEY}")
         @Import:
            1. 可以用来导入子配置类
     */
    @Configuration
    //@ComponentScan("com.itheima")
    //@PropertySource("db.properties")
    @Import(AppConfig01.class) //导入子配置类
    public class AppConfig {
        @Value("${db.driverClass}")
        private String driverClass;
    
        @Value("${db.jdbcUrl}")
        private String jdbcUrl;
    
        @Value("${db.user}")
        private String user;
    
        @Value("${db.password}")
        private String password;
    
        public void show(){
            System.out.println("driverClass = " + driverClass);
            System.out.println("jdbcUrl = " + jdbcUrl);
            System.out.println("user = " + user);
            System.out.println("password = " + password);
        }
    
        //==============================以下代码是说明@Bean=============================
    
        /*
            @Bean
                1. 打在方法身上,spring会来调用这个方法
                2. spring会把这个方法的返回值管理起来,丢到spring的工厂里面去
                3. 可以在@Bean的value属性里面设置对象的id,如果不设置,那么将会使用方法的名字作为id值
         */
    
        //1. 把QueryRunner对象交给spring管理,使用方法名字作为id值
        @Bean
        public QueryRunner runner01(){
            return new QueryRunner();
        }
    
        // 2. 把QueryRunner对象交给spring管理,使用属性来指定id值
        @Bean("run02")
        public QueryRunner runner02(){
            return new QueryRunner();
        }
    
        /*
            3.使用@Bean注解标记的方法,方法内部需要用到spring工厂(容器)里面的某一个对象,怎么办?
                3.1 此时可以在方法的参数上,写上想要的对象参数即可
                    a. 其实它就是在方法参数的前面,隐藏着一个注解: @Autowired
                3.2 但是也要考虑出现极端的情况:如果在spring的容器里面,有多个对象满足这个参数的类型,咋办?
                    a. 搭配使用@Qualifier ,指定id值。
                    b. 投机取巧,把方法的参数名字,写成id的名字即可
    
         */
        @Bean
        public QueryRunner runner03(@Qualifier("dataSource") DataSource ds){
            System.out.println("ds===" + ds);
            return new QueryRunner(ds);
        }
    
        @Bean
        public QueryRunner runner04(DataSource dataSource2){
            System.out.println("dataSource2===" + dataSource2);
            return new QueryRunner(dataSource2);
        }
    
        @Bean
        public DataSource dataSource() throws PropertyVetoException {
            ComboPooledDataSource ds = new ComboPooledDataSource();
            ds.setDriverClass(driverClass);
            ds.setJdbcUrl(jdbcUrl);
            ds.setUser(user);
            ds.setPassword(password);
            return ds;
        }
       @Bean
        public DataSource dataSource2() throws PropertyVetoException {
            ComboPooledDataSource ds = new ComboPooledDataSource();
            ds.setDriverClass(driverClass);
            ds.setJdbcUrl(jdbcUrl);
            ds.setUser(user);
            ds.setPassword(password);
            return ds;
        }
    }
    
    
    • 子配置类
    package com.itheima.config;
    
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.PropertySource;
    
    @ComponentScan("com.itheima")
    @PropertySource("db.properties")
    public class AppConfig01 {
    }
    
    
    3 @Bean声明bean
    1) @Bean定义bean
    • @Bean注解:方法级别的注解

      • 作用: 方法会由spring调用,并且把方法返回值声明成为一个bean,作用相当于标签 , 这个方法的返回值将会被Spring管理起来。

      • @Bean注解可以写在方法上,这些方法可以写在核心配置类里面,也可以写在其他的组件类里面,但是一般会写在核心配置类里面。

    • @Bean注解的属性:

      • value属性:bean的id。如果不设置,那么方法名就是bean的id
    @Configuration
    @ComponentScan("com.itheima")
    public class AppConfig {
        
        ...
    
        //==============================以下代码是说明@Bean=============================
    
        /*
            @Bean
                1. 打在方法身上,spring会来调用这个方法
                2. spring会把这个方法的返回值管理起来,丢到spring的工厂里面去
                3. 可以在@Bean的value属性里面设置对象的id,如果不设置,那么将会使用方法的名字作为id值
         */
    
        //1. 把QueryRunner对象交给spring管理,使用方法名字作为id值
        @Bean
        public QueryRunner runner01(){
            return new QueryRunner();
        }
    
        // 2. 把QueryRunner对象交给spring管理,使用属性来指定id值
        @Bean("run02")
        public QueryRunner runner02(){
            return new QueryRunner();
        }
    
        /*
            3.使用@Bean注解标记的方法,方法内部需要用到spring工厂(容器)里面的某一个对象,怎么办?
                3.1 此时可以在方法的参数上,写上想要的对象参数即可
                    a. 其实它就是在方法参数的前面,隐藏着一个注解: @Autowired
                3.2 但是也要考虑出现极端的情况:如果在spring的容器里面,有多个对象满足这个参数的类型,咋办?
                    a. 搭配使用@Qualifier ,指定id值。
                    b. 投机取巧,把方法的参数名字,写成id的名字即可
    
         */
        @Bean
        public QueryRunner runner03(@Qualifier("dataSource") DataSource ds){
            System.out.println("ds===" + ds);
            return new QueryRunner(ds);
        }
    
        @Bean
        public QueryRunner runner04(DataSource dataSource2){
            System.out.println("dataSource2===" + dataSource2);
            return new QueryRunner(dataSource2);
        }
    
        @Bean
        public DataSource dataSource() throws PropertyVetoException {
            ComboPooledDataSource ds = new ComboPooledDataSource();
            ds.setDriverClass(driverClass);
            ds.setJdbcUrl(jdbcUrl);
            ds.setUser(user);
            ds.setPassword(password);
            return ds;
        }
       @Bean
        public DataSource dataSource2() throws PropertyVetoException {
            ComboPooledDataSource ds = new ComboPooledDataSource();
            ds.setDriverClass(driverClass);
            ds.setJdbcUrl(jdbcUrl);
            ds.setUser(user);
            ds.setPassword(password);
            return ds;
        }
        
    
    }
    
    2) @Bean的依赖注入
    • @Bean注解的方法可以有任意参数,这些参数即是bean所需要的依赖,默认采用byType方式注入
    • 可以在方法参数上增加注解@Qualifier,用于byName注入
    3) 完整代码
    package com.itheima.config;
    
    import com.mchange.v2.c3p0.ComboPooledDataSource;
    import org.apache.commons.dbutils.QueryRunner;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.*;
    import org.springframework.stereotype.Component;
    
    import javax.annotation.Resource;
    import javax.sql.DataSource;
    import java.beans.PropertyVetoException;
    
    /*
        @Configuration:
            1. 表示这个类是一个核心配置类
            2. 它的作用等价于以前的applicationContext.xml
            3. @Configuration 是从@Component注解衍生出来的,所以这个类也会被spring管理起来(创建对象)
        @ComponentScan :
            1. 用来指定扫描包,等价于 
        @PropertyScource:
            1. 用来导入外部的properties文件,等价于
            2. 导入这个properties文件的时候,如果有错(1. 找不到这个文件,2.这个文件无法打开,)可以在
                名字的前面加上 classpath:
            3. 要想把properties里面的内容注入进来,就需要定义好对应的属性,然后使用@Value来注入值
                @Value("${KEY}")
         @Import:
            1. 可以用来导入子配置类
     */
    @Configuration
    //@ComponentScan("com.itheima")
    //@PropertySource("db.properties")
    @Import(AppConfig01.class) //导入子配置类
    public class AppConfig {
        @Value("${db.driverClass}")
        private String driverClass;
    
        @Value("${db.jdbcUrl}")
        private String jdbcUrl;
    
        @Value("${db.user}")
        private String user;
    
        @Value("${db.password}")
        private String password;
    
        public void show(){
            System.out.println("driverClass = " + driverClass);
            System.out.println("jdbcUrl = " + jdbcUrl);
            System.out.println("user = " + user);
            System.out.println("password = " + password);
        }
    
        //==============================以下代码是说明@Bean=============================
    
        /*
            @Bean
                1. 打在方法身上,spring会来调用这个方法
                2. spring会把这个方法的返回值管理起来,丢到spring的工厂里面去
                3. 可以在@Bean的value属性里面设置对象的id,如果不设置,那么将会使用方法的名字作为id值
         */
    
        //1. 把QueryRunner对象交给spring管理,使用方法名字作为id值
        @Bean
        public QueryRunner runner01(){
            return new QueryRunner();
        }
    
        // 2. 把QueryRunner对象交给spring管理,使用属性来指定id值
        @Bean("run02")
        public QueryRunner runner02(){
            return new QueryRunner();
        }
    
        /*
            3.使用@Bean注解标记的方法,方法内部需要用到spring工厂(容器)里面的某一个对象,怎么办?
                3.1 此时可以在方法的参数上,写上想要的对象参数即可
                    a. 其实它就是在方法参数的前面,隐藏着一个注解: @Autowired
                3.2 但是也要考虑出现极端的情况:如果在spring的容器里面,有多个对象满足这个参数的类型,咋办?
                    a. 搭配使用@Qualifier ,指定id值。
                    b. 投机取巧,把方法的参数名字,写成id的名字即可
    
         */
        @Bean
        public QueryRunner runner03(@Qualifier("dataSource") DataSource ds){
            System.out.println("ds===" + ds);
            return new QueryRunner(ds);
        }
    
        @Bean
        public QueryRunner runner04(DataSource dataSource2){
            System.out.println("dataSource2===" + dataSource2);
            return new QueryRunner(dataSource2);
        }
    
        @Bean
        public DataSource dataSource() throws PropertyVetoException {
            ComboPooledDataSource ds = new ComboPooledDataSource();
            ds.setDriverClass(driverClass);
            ds.setJdbcUrl(jdbcUrl);
            ds.setUser(user);
            ds.setPassword(password);
            return ds;
        }
       @Bean
        public DataSource dataSource2() throws PropertyVetoException {
            ComboPooledDataSource ds = new ComboPooledDataSource();
            ds.setDriverClass(driverClass);
            ds.setJdbcUrl(jdbcUrl);
            ds.setUser(user);
            ds.setPassword(password);
            return ds;
        }
    }
    
    

    小结

    • 配置类上要加注解@Configuration 变成核心配置类,主要是用来替代applicationContext.xml

    • 要开启组件扫描,在配置类上@ComponentScan("com.itheima")

    • 如果要把jar包里的类注册成bean:

      • 在配置类里加方法,方法上加@Bean,会把方法返回值注册bean对象
    • 如果要引入外部的properties文件,在配置类上加@PropertySource("classpath:xxx.properties")

    • 引入模块配置类,在配置类上使用@Import(子配置类.class)

    • @Bean ,如果期望让spring来管理某个方法的返回值(注意: 这个返回值大多数都是对象,很少是一个普通的数据,比如:数字、字符串…)

    四、整合Mybatis

    1. 导入依赖

    <dependencies>
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-contextartifactId>
                <version>5.1.2.RELEASEversion>
            dependency>
    
            <dependency>
                <groupId>junitgroupId>
                <artifactId>junitartifactId>
                <version>4.12version>
                <scope>testscope>
            dependency>
    
            
            
            
            
            
            
            <dependency>
                <groupId>com.mchangegroupId>
                <artifactId>c3p0artifactId>
                <version>0.9.5.4version>
            dependency>
    
    
            
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-jdbcartifactId>
                <version>5.1.2.RELEASEversion>
            dependency>
            
            <dependency>
                <groupId>org.mybatisgroupId>
                <artifactId>mybatis-springartifactId>
                <version>2.0.5version>
            dependency>
    
            <dependency>
                <groupId>org.mybatisgroupId>
                <artifactId>mybatisartifactId>
                <version>3.5.5version>
            dependency>
            
            <dependency>
                <groupId>mysqlgroupId>
                <artifactId>mysql-connector-javaartifactId>
                <version>5.1.32version>
            dependency>
    
            
            <dependency>
                <groupId>org.slf4jgroupId>
                <artifactId>slf4j-apiartifactId>
                <version>1.7.20version>
            dependency>
            
            <dependency>
                <groupId>ch.qos.logbackgroupId>
                <artifactId>logback-classicartifactId>
                <version>1.2.3version>
            dependency>
            
            <dependency>
                <groupId>ch.qos.logbackgroupId>
                <artifactId>logback-coreartifactId>
                <version>1.2.3version>
            dependency>
    
        dependencies>
    

    2. 定义dao接口和映射文件

    • 接口
    package com.itheima.dao;
    
    import com.itheima.bean.Brand;
    import org.springframework.stereotype.Repository;
    
    import java.util.List;
    
    
    public interface BrandDao {
    
        List<Brand> findAll();
    
    }
    
    
    • 注解形式配置SQL语句

      @Results(id="brandMap" , value = {
                  @Result(column = "brand_name" , property = "brandName"),
                  @Result(column = "company_name" , property = "companyName"),
          })
          @Select("select * from tb_brand")
          List<Brand> findAll();
      
    • 映射文件

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.itheima.dao.BrandDao">
    
        <resultMap id="brandMap" type="Brand">
            <result column="brand_name" property="brandName"/>
            <result column="company_name" property="companyName"/>
        </resultMap>
    
        <select id="findAll"  resultMap="brandMap">
            select * from tb_brand
        </select>
    </mapper>
    

    3. 定义service接口和实现

    • 接口
    package com.itheima.service;
    
    import com.itheima.bean.Brand;
    
    import java.util.List;
    
    public interface BrandService {
    
        /**
         * 查询所有
         * @return
         */
        List<Brand> findAll();
    }
    
    
    • 实现
    package com.itheima.service.impl;
    
    import com.itheima.bean.Brand;
    import com.itheima.dao.BrandDao;
    import com.itheima.service.BrandService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    
    /*
        需求:
            在service里面调用dao的findAll方法。
        步骤:
            1. 不写mybatis的核心配置文件了,但是核心配置文件的内容还是需要有的。由spring来接管这个工作。
            2.  mybatis的核心配置文件里面包含两个部分的内容: 环境配置和映射文件配置
                2.1 环境配置由 SqlSessionFactoryBean类来接管
                2.2 映射文件配置由MapperScannerConfigure类来接管
            3. 以上的两个类需要在applicationContext.xml中定义出来!
    
            4. 在service类上打注解: @Service
            5. 在service里面定义出来dao的属性,然后在属性上打注解 : @Autowired
     */
    @Service
    public class BrandServiceImpl implements BrandService {
    
        @Autowired
        private BrandDao brandDao;
    
        @Override
        public List<Brand> findAll() {
            System.out.println("调用了BrandServiceImpl的findAll方法~!");
            return brandDao.findAll();
        }
    }
    

    4. 定义配置文件

    • db.properties
    db.driverClass=com.mysql.jdbc.Driver
    db.jdbcUrl=jdbc:mysql://localhost:3306/day29_demo
    db.user=root
    db.password=root
    
    • AppConfig.java
    
    @Configuration // 表示这个类是一个核心配置类,等价于:applicationContext.xml
    @ComponentScan("com.itheima") // 组件扫描
    @PropertySource("classpath:db.properties") // 导入properties文件
    public class AppConfig {
    
        @Value("${db.driverClass}")
        private String driverClass;
    
        @Value("${db.jdbcUrl}")
        private String jdbcUrl;
    
        @Value("${db.user}")
        private String user;
    
        @Value("${db.password}")
        private String password;
    
    
        @Bean
        public DataSource ds() throws PropertyVetoException {
    
            ComboPooledDataSource ds = new ComboPooledDataSource();
    
            
            ds.setDriverClass("com.mysql.jdbc.Driver");
            ds.setJdbcUrl("jdbc:mysql://localhost:3306/day29_demo");
            ds.setUser("root");
            ds.setPassword("root");
    
            return ds;
        }
    
        @Bean   
        public SqlSessionFactoryBean factoryBean(DataSource ds){
             SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
             bean.setTypeAliasesPackage("com.itheima.bean");
             bean.setDataSource(ds);
             return bean;
        }
    
        @Bean
               //单独这样写会报错
        public MapperScannerConfigurer configurer(){
            MapperScannerConfigurer m = new MapperScannerConfigurer();
            m.setBasePackage("com.itheima.dao");
            return m;
        }
    }
    
    

    扫描mapper的这个方法会有问题:

    1. 首先要理解整个代码的执行过程:

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

    1. 原因分析:
    /*
        1. 如果在类当中使用了MapperScannerConfigurer ,那么将会导致 AppConfig类被初始化的时机提前,使得属性都无法完成注入。
        2. 解决的办法:
            2.1 把这个方法标记成 static 静态方法
            2.2 把这个方法放到隔壁的配置类中,然后在这个类里面使用 @Import来导入它
            2.3 不写这个方法了,只需要在配置类上打上注解 @MapperScan("com.itheima.dao")    */
        @Bean
        public MapperScannerConfigurer msc() {
            MapperScannerConfigurer msc = new MapperScannerConfigurer();
            msc.setBasePackage("com.itheima.dao");
            return msc;
        }
    

    5. 单元测试

    package com.itheima.test;
    
    import com.itheima.service.BrandService;
    import com.itheima.service.impl.BrandServiceImpl;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class TestBrandServiceImpl {
    
        @Test
        public void testFindAll(){
    
            //1. 创建工厂
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    
            //2. 问工厂要对象
            BrandService bs = context.getBean(BrandServiceImpl.class);
    
            //3. 调用方法
            System.out.println(bs.findAll());
        }
    }
    

    五、Spring整合Junit【掌握】

    ​ 在上边的CURD中,单元测试类里还需要我们自己去创建ApplicationContext,并自己去获取bean对象。Spring提供了整合Junit的方法,让单元测试更简洁方便。

    注解简介

    注解说明
    @RunWith用在测试类上,用于声明不再使用Junit,而是使用Spring提供的运行环境
    @ContextConfiguration用在测试类上,用于指定Spring配置类、或者Spring的配置文件

    Spring提供了单元测试的运行环境:SpringJunit4ClassRunner,配置到@RunWith注解上:

    @RunWith(SpringJunit4ClassRunner.class)

    • 要使用以上注解,需要导入jar包依赖:spring-testjunit
     <dependencies>
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-testartifactId>
                <version>5.1.2.RELEASEversion>
            dependency>
    
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-contextartifactId>
                <version>5.1.2.RELEASEversion>
            dependency>
    
            <dependency>
                <groupId>junitgroupId>
                <artifactId>junitartifactId>
                <version>4.12version>
            dependency>
        dependencies>
    

    使用示例

    步骤
    1. 在pom.xml文件中增加依赖:spring-testjunit

    2. 修改单元测试类

      1. 在单元测试类上增加注解:@RunWith(SpringJunit4ClassRunner.class)

        目的:使用Spring的单元测试运行器,替换Junit原生的运行器

      2. 在单元测试类上增加注解:@ContextConfiguration()

        目的:指定配置文件或配置类

      3. 在测试类里的依赖项上,直接使用@Autowired注入依赖

    实现
    1. 在pom.xml文件中增加依赖:spring-testjunit

       <dependencies>
              
              <dependency>
                  <groupId>org.springframeworkgroupId>
                  <artifactId>spring-contextartifactId>
                  <version>5.1.2.RELEASEversion>
              dependency>
      
              
              <dependency>
                  <groupId>org.springframeworkgroupId>
                  <artifactId>spring-testartifactId>
                  <version>5.1.2.RELEASEversion>
              dependency>
      
              
              <dependency>
                  <groupId>junitgroupId>
                  <artifactId>junitartifactId>
                  <version>4.12version>
              dependency>
      
          dependencies>
      
    2. UserService接口

    package com.itheima.service;
    
    public interface UserService {
        void add();
    }
    
    1. UserServiceImpl实现类
    package com.itheima.service.impl;
    
    import com.itheima.service.UserService;
    
    public class UserServiceImpl implements UserService {
        public void add() {
            System.out.println("调用了UserServiceImpl的add方法!~");
        }
    }
    
    
    1. applicationContext.xml
    
    <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="us" class="com.itheima.service.impl.UserServiceImpl"/>
    beans>
    
    1. 修改单元测试类
    package com.itheima.test;
    
    import com.itheima.service.UserService;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    
    /*
        @RunWith
            1. 表示使用的单元测试的环境,不再是以前的Junit的测试环境,而是spring针对Junit提供的测试环境
            2. 这套spring提供的测试环境在背后会帮助我们创建工厂。
        @ContextConfiguration
            1. 告诉spring的测试环境,配置文件在哪里?
            2. classpath: 这是固定写法,表示要在类路径底下找配置文件。
     */
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:applicationContext.xml")
    public class TestUserServiceImpl02 {
    
        //让spring把想要用到的对象给注入进来!
        // 这个注解是自动注入的意思,让spring把对象注入进来。明天讲!
        @Autowired
        private UserService us;
    
        @Test
        public void testAdd(){
    
            /*ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    
            UserService us = (UserService) context.getBean("us");
            */
            us.add();
    
        }
    }
    
    

    小结

    1. 导入依赖

    2. 在测试类上打注解

    3. 直接在测试类里面使用@Autowired注入对象。

    六、Lombok

    /*
        使用lombok的先决条件;
            1. idea安装lombok插件 : 目的是为了生成代码
            2. 项目导入lombok的依赖: 目的是为了写注解
    
            @AllArgsConstructor :  用来创建满参的构造函数
            @NoArgsConstructor: 用来创建无参的构造函数
    
            @Setter : 用来生成set方法
            @Getter : 用来生成get方法
            @ToString: 用来生成 toString方法
    
            @Data :
                创建get 和 set 和 toString方法
    
            @Builder:
                会生成构建者对象,使用它可以更加灵活的构建的JavaBean对象!
     */
    
    @Builder
    @Data
    @ToString
    @Setter
    @Getter
    @AllArgsConstructor
    @NoArgsConstructor
    public class Brand {
        private int id;
        private String brandName;
        private String cName;
        private String description;
        private int status;
        private int ordered;
    
        private List<String> list = new ArrayList<>();
    }
    

    @Data 其实还包含equals那些方法

  • 相关阅读:
    Xilinx FPGA DDR3设计(三)DDR3 IP核详解及读写测试
    FreeRTOS个人笔记-FreeRTOSConfig.h
    leetcode-电话号码组合(C CODE)
    设备通过国标GB28181接入EasyCVR平台,出现断流情况该如何解决?
    Redis混合模式下的持久化原理
    加速化工行业数字腾飞,S2B2C电商供应链系统成企业新增长引擎
    # 技术栈知识点巩固——Nginx
    pyqt5:pandas 读取 Excel文件或 .etx 电子表格文件,并显示
    [MySQL][表的增删查改][二][Retrieve][SELECT][WHERE]详细讲解
    为什么大型工程团队要在 Kubernetes 上进行测试?
  • 原文地址:https://blog.csdn.net/weixin_66490956/article/details/127114511