首页 > 其他分享 >Spring-day02

Spring-day02

时间:2023-03-11 16:33:17浏览次数:34  
标签:spring Spring void public user day02 注解 class

Spring-day02

01_开启Spring注解

目标

  • 能够设置Spring的注解扫描

路径

  1. 注解开发的意义
  2. 在配置文件中开启Spring注解扫描

注解开发的意义

在Spring中除了可以使用xml配置IoC外,还可以使用注解配置IoC

  • 注解配置相对xml方式会比较简洁,但是阅读性也会差一些

Spring启动时使用注解的形式替代xml配置,将繁杂的spring配置文件从工程中彻底消除掉,简化书写

1591023265469

注解配置的弊端:

  • 注解的配置需要基于源代码
    • 为了达成注解驱动的目的,可能会将原先很简单的书写,变的更加复杂

在配置文件中开启Spring注解扫描

在Spring中要使用注解配置,要启动注解扫描:

  • 根据指定的包名,加载类中配置的注解项
<context:component-scan base-package="packageName"/>

说明:

  • 在进行包扫描时,会对配置的包及其子包中所有文件进行扫描

  • 扫描过程是以文件夹递归迭代的形式进行的

  • 扫描过程仅读取合法的java文件

  • 扫描时仅读取spring可识别的注解

  • 扫描结束后会将可识别的有效注解转化为spring对应的资源加入IoC容器

注意:

  • 无论是注解格式还是XML配置格式,最终都是将资源加载到IoC容器中,差别仅仅是数据读取方式不同

    • 从加载效率上来说注解优于XML配置文件

02_IoC的注解配置-装配bean

目标

  • 能够使用@Component注解装配bean

路径

  1. @Component注解介绍
  2. 使用@Component注解装配bean

@Component注解介绍

在Spring中使用@Component注解,设置类为spring管理的bean

@Component   //相当于在xml中配置:<bean id="" class="">
public class ClassName{
}

@Component注解中的属性:

  • value : 指定bean的id。如果不指定value属性,默认bean的id是当前类的类名(首字母小写)。
@Component("service") //相当于在xml中配置:<bean id="service" class="包.UserServiceImpl">
public class UserServiceImpl implements UserService{
}

使用@Component注解装配bean

在Spring中使用注解的步骤:

  1. 开启spring注解扫描
  2. 在类上添加@Component注解

代码示例:

  • 配置文件
<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">


    <!-- 开启spring注解扫描
         spring扫描指定包下的类,加载配置了注解的类
    -->
    <context:component-scan base-package="com.itheima"/>

</beans>
  • 业务层
//接口
public interface IUserService {
    public void saveUser(User user);
}

//实现类
@Component("userService")
public class UserServiceImpl implements IUserService {
    @Override
    public void saveUser(User user) {
        System.out.println("UserSerive => saveUser方法");
    }
}
  • 测试类
public class UserServiceTest {

    private IUserService userService;//业务对象

    @Before
    public void initUserService() {
        //加载配置文件初始化容器
        ApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");

        //从容器中获取对象
        userService = (IUserService) cxt.getBean("userService");
    }

    
    @Test
    public void testSaveUser() {
        //创建User对象
        User user = new User("黑马","123123");

        userService.saveUser(user);
    }
}

03_IoC的注解配置-衍生注解

目标

  • 能够使用衍生注解装配bean

路径

  1. 衍生注解介绍
  2. 使用衍生注解装配bean

衍生注解介绍

在@Component注解下,衍生了@Controller、@Service 、@Repository三个注解。功能同等于@Component

  • 衍生注解提供了更加明确的语义
    • @Controller:一般用于表现层的注解
    • @Service:一般用于业务层的注解
    • @Repository:一般用于持久层的注解

使用衍生注解装配bean

使用衍生注解完成bean的装配:

1、 使用@Service注解装配service的实现类

2、 使用@Respository注解装配dao的实现类

代码示例:

  • 配置文件
<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">


    <!-- 开启spring注解扫描
         spring扫描指定包下的类,加载配置了注解的类
    -->
    <context:component-scan base-package="com.itheima"/>

</beans>
  • Dao层(持久层)
//接口
public interface IUserDao {
    public void addUser(User user);
}


//实现类
@Repository("userDao")
public class UserDaoImpl implements IUserDao{
    /**
     * 添加用户
     * @param user
     */
    @Override
    public void addUser(User user) {
        System.out.println("UserDao => addUser方法");
    }
}
  • 业务层
//接口
public interface IUserService {
    public void saveUser(User user);
}

//实现类
@Service("userService")
public class UserServiceImpl implements IUserService {
    @Override
    public void saveUser(User user) {
        System.out.println("UserSerive => saveUser方法");
    }
}
  • 测试类
//测试dao层
public class UserDaoTest {
    private IUserDao userDao;

    @Before
    public void initUserService() {
        //加载配置文件初始化容器
        ApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");

        //从容器中获取对象
        userDao = (IUserDao) cxt.getBean("userDao");
    }

    @Test
    public void testAddUser() {
        //创建User对象
        User user = new User("黑马", "123123");

        userDao.addUser(user);
    }
}



//测试业务层
public class UserServiceTest {

    private IUserService userService;

    @Before
    public void initUserService() {
        //加载配置文件初始化容器
        ApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");

        //从容器中获取对象
        userService = (IUserService) cxt.getBean("userService");
    }

    @Test
    public void testSaveUser() {
        //创建User对象
        User user = new User("黑马","123123");

        userService.saveUser(user);
    }
}
虽然从spring容器中单独获取service的实现类和dao的实现类都没有问题。
但是当在service实现类中加入dao对象后时,发现会报空指针异常

image-20220423141809291

原因是service的实现类中调用了dao的实现类,但是dao的实现类对象并没有被注入到service的实现类中,因此造成了空指针异常。
原因分析:我们仅仅使用注解装配了bean,但是并没有将dao注入到service中。
解决方案:使用注解注入

04_IoC的注解配置-属性注入1

目标

  • 能够使用@Autowired或@Qualifier实现引用类型属性注入

路径

  1. @Autowired注解介绍
  2. 使用@Autowired向业务类中注入dao对象
  3. @Qualifier注解介绍

@Autowired注解介绍

@Autowired注解:

public class ClassName{
    @Autowired
    private 引用类型 对象名;
}
  • 作用:按照类型注入引用类型对象
    • 当容器中只有一个类型匹配的对象时直接注入
    • 当有多个类型匹配的对象时,使用要注入的对象的变量名称作为bean的id,在spring容器查找,找到了也可以注入成功,找不到就报错。
  • 细节:当使用注解注入属性时,可以省略setter方法

image-20220512103831305

使用@Autowired向业务类中注入dao对象

代码示例:

  • 业务层
@Service("userService")
public class UserServiceImpl implements IUserService {
    @Autowired  //自动按照类型注入
    private IUserDao userDao;//dao层对象

    @Override
    public void saveUser(User user) {
        System.out.println("UserSerive => saveUser方法");
        userDao.addUser(user);
    }
}
  • 测试类
public class UserServiceTest {
    private IUserService userService;

    @Before
    public void initUserService() {
        //加载配置文件初始化容器
        ApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");

        //从容器中获取对象
        userService = (IUserService) cxt.getBean("userService");
    }

    @Test
    public void testSaveUser() {
        //创建User对象
        User user = new User("黑马","123123");

        userService.saveUser(user);
    }
}
//输出结果:
UserSerive => saveUser方法
UserDao => addUser方法
@Autowired注解的属性: 
     required (通常不用书写)[了解即可]
     取值:
         true: 此对象必须注入成功,若不成功则报错 (默认值)
         false: 可以注入不成功,此对象为null

@Qualifier注解介绍

@Qualifier注解:

public class ClassName{
    @Autowired
    @Qualifier("beanId")
    private 引用类型 对象名;
}
  • 作用:在自动按照类型注入(@Autowired)的基础之上,再按照bean的id注入

  • 应用场景:

    在使用@Autowired注入,当有多个类型匹配的对象时:
    按照@Qualifier("beanId")注解指定beanId进行注入
    
  • 属性: value , 指定bean的id

  • 注意事项:@Qualifier注解不能独立使用,必须和@Autowired一起使用

代码示例:

  • Dao层 (有多个类型相同的Dao对象)
//第1个:IUserDao
@Repository("userDao")
public class UserDaoImpl implements IUserDao {
    @Override
    public void addUser(User user) {
        System.out.println("UserDao => addUser方法");
    }
}


//第2个:IUserDao
@Repository("userDao2")
public class UserDaoImpl2 implements IUserDao {
    @Override
    public void addUser(User user) {
        System.out.println("UserDao2 => addUser方法");
    }
}
  • 业务层
@Service("userService")
public class UserServiceImpl implements IUserService {
    @Autowired
    @Qualifier("userDao2") //从容器中获取名为"userDao2"的对象注入
    private IUserDao userDao;

    @Override
    public void saveUser(User user) {
        System.out.println("UserSerive => saveUser方法");
        userDao.addUser(user);
    }
}

05_IoC的注解配置-属性注入2

目标

  • 能够使用@Value实现非引用类型属性注入

路径

  1. @Value注解介绍
  2. 使用@Value向基本类型或String类型属性注入数据

@Value注解介绍

@Value注解:

public class ClassName{
    @Value("100")
    private int num;
    @Value("黑马")
    private String name;
}
  • 说明:

    • value值仅支持基本数据、String类型、包装类类型

    • value值支持读取properties文件中的属性值

    • value值支持SpringEL表达式

    • @value注解如果添加在属性上方,可以省略setter方法

  • 相关属性

    • value(默认):定义对应的属性值

使用@Value向基本类型或String类型属性注入数据

代码示例:

  • 业务层
@Service("userService2")
public class UserServiceImpl2 implements IUserService {
    @Value("1000")
    private int num; //基本类型
    @Value("黑马")
    private String name; //String类型
    @Value("20")
    private Integer age; //Integer类型(包装类)

    @Autowired
    private IUserDao userDao;

    @Override
    public void saveUser(User user) {
        System.out.println("UserSerive2 => saveUser方法");

        System.out.println("int类型:"+num);
        System.out.println("String类型:"+name);
        System.out.println("包装类类型:"+age);

        userDao.addUser(user);
    }
}
  • 测试类
public class UserServiceTest {
    private IUserService userService;

    @Before
    public void initUserService() {
        //加载配置文件初始化容器
        ApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");

        //从容器中获取对象
        userService = (IUserService) cxt.getBean("userService2");
    }

    @Test
    public void testSaveUser() {
        //创建User对象
        User user = new User("黑马","123123");    
        userService.saveUser(user);
    }
}
//输出结果:
UserSerive2 => saveUser方法
int类型:1000
String类型:黑马
包装类类型:20
UserDao => addUser方法

06_IoC的注解配置-加载properties文件

目标

  • 能够使用@PropertySource加载properties文件

路径

  1. @PropertySource注解介绍
  2. 使用@PropertySource加载properties文件

@PropertySource注解介绍

@PropertySource注解:

@PropertySource(value = "文件名.properties")
public class ClassName {
    @Value("${properties文件中的属性名}")
    private String attributeName;
}
  • 作用:加载外部properties配置文件
  • 属性:value , 设置加载的properties文件名

使用@PropertySource加载properties文件

代码示例:

  • properties文件
name=heima
num=10
  • 业务层
@Service("userService2")
@PropertySource(value = "data.properties") //引入外部properties配置文件
public class UserServiceImpl2 implements IUserService {
    @Value("${num}") //获取配置文件中的数据
    private int num;  
    @Value("${name}")
    private String name; 
    @Value("${age}")
    private Integer age; 

    @Autowired
    private IUserDao userDao;

    @Override
    public void saveUser(User user) {
        System.out.println("UserSerive2 => saveUser方法");

        System.out.println("int类型:"+num);
        System.out.println("String类型:"+name);
        System.out.println("包装类类型:"+age);

        userDao.addUser(user);
    }
}
  • 测试类
public class UserServiceTest {
    private IUserService userService;

    @Before
    public void initUserService() {
        //加载配置文件初始化容器
        ApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");

        //从容器中获取对象
        userService = (IUserService) cxt.getBean("userService2");
    }

    @Test
    public void testSaveUser() {
        //创建User对象
        User user = new User("黑马","123123");

        userService.saveUser(user);
    }
}
//输出结果:
UserSerive2 => saveUser方法
int类型:10
String类型:heima
包装类类型:20
UserDao => addUser方法

小结

从外部资源文件中获取数据:

  1. 使用:@PropertySource注解,加载外部配置文件
  2. 使用:@Value注解+SpringEL表达式,获取配置文件中的数据

07_IoC的注解配置-纯注解开发

目标

  • 能够使用Spring纯注解方式编写程序

路径

  1. @Configuration注解介绍
  2. @ComponentScan注解介绍
  3. 使用纯注解形式开发

取消spring的xml配置文件,使用纯注解开发模式:

  1. 指定配置类,代替xml配置文件
  2. 在配置类中指定要扫描的包
  3. 使用AnnotationConfigApplicationContext类代替ClassPathXmlApplicationContext类

@Configuration注解介绍

@Configuration注解

@Configuration
public class SpringConfig{
}

作用:指定当前类是一个spring配置类,当创建容器时会从该类上加载注解

  • 简单来讲:就是替换掉spring的xml配置文件(不在使用applicationContext.xml配置文件了)

面临的问题:使用配置类代替了XML配置文件了,但是如何配置创建容器时要扫描的包呢?

  • 使用:@ComponentScan注解

@ComponentScan注解介绍

@ComponentScan注解:

@Configuration
@ComponentScan("包名路径")
public class SpringConfig{
}
  • 作用:用于指定spring在初始化容器时要扫描的包

    • 和xml配置文件中的功能一样

      <context:component-scan base-package="包名路径"/>
      
  • 属性: value , 用于指定要扫描的包。和标签中的base-Package属性作用一样。

使用纯注解形式开发

纯注解方式开发:使用AnnotationConfigApplicationContext类加载注解配置

image-20220417122831926

获取容器时要使用:AnnotationApplicationContext(有@Configuration注解的类.class)

ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);

代码示例:

  • 配置类
@Configuration  //当前类是Spring配置类
@ComponentScan("com.itheima")//指定扫描的包
@PropertySource(value = "data.properties")//加载外部资源文件
public class SpringConfig {
}
  • 业务类
@Service("userService2")
//@PropertySource(value = "data.properties") //可以删除(配置类中已加载了外部配置文件)
public class UserServiceImpl2 implements IUserService {
    @Value("${num}")
    private int num; //基本类型
    @Value("${name}")
    private String name; //String类型
    @Value("${age}")
    private Integer age; //Integer类型(包装类)

    @Autowired
    private IUserDao userDao;

    @Override
    public void saveUser(User user) {
        System.out.println("UserSerive2 => saveUser方法");

        System.out.println("int类型:"+num);
        System.out.println("String类型:"+name);
        System.out.println("包装类类型:"+age);

        userDao.addUser(user);
    }
}
  • 测试类
public class UserServiceTest2 {
    private IUserService userService;

    @Before
    public void initUserService() {
        //加载配置类初始化容器 (不使用XML配置文件了)
       ApplicationContext cxt = new AnnotationConfigApplicationContext(SpringConfig.class); 

        //从容器中获取对象
        userService = (IUserService) cxt.getBean("userService2");
    }

    @Test
    public void testSaveUser() {
        //创建User对象
        User user = new User("黑马","123123");
        userService.saveUser(user);
    }
}

小结

使用纯注解形式开发Spring的步骤:

  1. 创建Spring配置类(代替xml配置文件)
    • 使用:@Configurable注解表示当前类为配置类
  2. 在Spring配置类上,指定要扫描的包路径
    • 使用:@ComponentScan注解指定扫描的包
  3. 使用AnnotationConfigApplicationContext创建Spring容器

08_IoC的注解配置-加载第三方资源

目标

  • 能够使用@Bean注解装配bean

路径

  1. @Bean注解介绍
  2. 使用@Bean加载第三方资源
  3. 第三方bean配置与管理

在XML配置文件中,可以把第三方框架(例:Druid)中的类,配置到spring容器中

<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 配置Druid中的类,作为Spring容器中的一个资源 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://127.0.0.1:3306/db1"></property>
        <property name="username" value="root"></property>
        <property name="password" value="itheima"></property>
    </bean>
</beans>
  • 通过bean标签的id值,就可以获取到第三方框架中类的对象

问题:当使用纯注解开发模式后,就取消了XML配置文件,如果要从spring容器中获取第三框架中的类,怎么办?

答案:第三方框架的bean是无法在其源码上进行修改,可以使用@Bean实现第三方bean的引入

@Bean注解介绍

@Bean注解:

@Component
public class ClassName{
    @Bean("名字")
    public 返回值类型 方法名(){
        return 返回值;    
    }
}
  • 作用:设置方法的返回值作为spring管理的bean(将方法的返回值作为一个bean,并且放入spring容器)
  • 属性:value , 定义bean的访问id

说明:

  • @Bean注解用于替代XML配置中的静态工厂与实例工厂创建bean(不区分方法是否为静态或非静态)
  • @Bean所在的类必须被spring扫描加载,否则该注解无法生效

使用@Bean加载第三方资源

代码示例:

  • 第三方资源
@Component  //@Bean所在的类必须被spring扫描加载,否则该注解无法生效
public class MyDataSource {

    @Bean("druidDataSource")  //bean的id名(spring容器中资源的名字)
    public DataSource createDruidDataSource(){
        //创建第三方资源对象
        DruidDataSource druidDataSource = new DruidDataSource();
        //设置参数
        druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
        druidDataSource.setUrl("jdbc:mysql://127.0.0.1:3306/db1");
        druidDataSource.setUsername("root");
        druidDataSource.setPassword("itheima");
        //返回对象
        return druidDataSource;
    }
}
  • Dao层
@Repository("userDao")
public class UserDaoImpl implements IUserDao {
    @Autowired
    @Qualifier("druidDataSource") //指定bean的名字
    private DataSource dataSource;

    /**
     * 添加用户
     * @param user
     */
    @Override
    public void addUser(User user) {
        System.out.println("UserDao => addUser方法");
        
        try {
            System.out.println("数据库连接状态:"+dataSource.getConnection().isClosed());
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
}
  • 测试类
public class UserDaoTest2 {
    private IUserDao userDao;

    @Before
    public void initUserService() {
        //加载配置类初始化容器
        ApplicationContext cxt = new AnnotationConfigApplicationContext(SpringConfig.class);

        //从容器中获取对象
        userDao = (IUserDao) cxt.getBean("userDao");
    }

    @Test
    public void testAddUser() {
        //创建User对象
        User user = new User("黑马", "123123");

        userDao.addUser(user);
    }
}

//输出结果:
UserDao => addUser方法
数据库连接是否关闭:false

第三方bean配置与管理

以上程序代码中,使用@Component注解,保证第三方框架中的类可以被spring扫描加载

除了这种方式外,还可以使用@Import注解,导入第三方bean作为spring控制的资源

@Import注解:

@Import(MyDataSource.class)
public class ClassName {
}

说明:

  • @Import注解在同一个类上,仅允许添加一次,如果需要导入多个,使用数组的形式进行设定

    @Import(value = {MyDataSource.class, MyDS.class , .... })//按照顺序加载
    //@Import(...)//同一个类上,不允许出现2次Import
    public class ClassName {
    }
    
  • 在被导入的类中可以继续使用@Import导入其他资源(了解)

  • @Bean所在的类可以使用导入的形式进入spring容器,无需声明为bean

代码示例:

  • 配置类
@Configurable  //当前类是Spring配置类
@ComponentScan("com.itheima")//指定扫描的包
@PropertySource(value = "data.properties")//加载外部资源文件
@Import(MyDataSource.class)  //导入MyDataSource类
public class SpringConfig {
}
  • 第三方资源Bean
//@Component   //可以删除  (在配置类中导入了MyDataSource类)
public class MyDataSource {

    @Bean("druidDataSource")  //bean的id名(spring容器中资源的名字)
    public DataSource createDruidDataSource(){
        //创建第三方资源对象
        DruidDataSource druidDataSource = new DruidDataSource();
        //设置参数
        druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
        druidDataSource.setUrl("jdbc:mysql://127.0.0.1:3306/db1");
        druidDataSource.setUsername("root");
        druidDataSource.setPassword("itheima");
        //返回对象
        return druidDataSource;
    }
}

另一种方式:直接在SpringConfig配置类中添加第三方Bean资源

@Configurable  //当前类是Spring配置类
@ComponentScan("com.itheima")//指定扫描的包
@PropertySource(value = "data.properties")//加载外部资源文件
public class SpringConfig {
    
    @Bean("druidDataSource")  //bean的id名(spring容器中资源的名字)
    public DataSource createDruidDataSource(){
        //创建第三方资源对象
        DruidDataSource druidDataSource = new DruidDataSource();
        //设置参数
        druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
        druidDataSource.setUrl("jdbc:mysql://127.0.0.1:3306/db1");
        druidDataSource.setUsername("root");
        druidDataSource.setPassword("itheima");
        //返回对象
        return druidDataSource;
    }
}

09_IoC的注解配置-bean作用域

目标

  • 了解@Scope设置bean作用域的方式

路径

  1. @Scope注解介绍
  2. 使用@Scope设置Bean作用域

@Scope注解介绍

@Scope注解:

@Component
@Scope
public class ClassName{
}
  • 作用:设置该类作为bean对应的scope属性
  • 属性:value ,定义bean的作用域。(默认为singleton)

使用@Scope设置Bean作用域

代码示例:

  • Dao层
@Repository("userDao2")
@Scope("singleton")    //单例
//@Scope("prototype")  //非单例
public class UserDaoImpl2 implements IUserDao {
    public UserDaoImpl2(){
        System.out.println("UserDaoImpl2构造方法...");
    }
    /**
     * 添加用户
     * @param user
     */
    @Override
    public void addUser(User user) {
        System.out.println("UserDao2 => addUser方法");
    }
}

  • 测试类
public class UserDaoTest3 {
    @Test
    public void testBeanScope(){
        //加载配置类初始化容器
        ApplicationContext cxt = new AnnotationConfigApplicationContext(SpringConfig.class);

        //从容器中获取对象
        IUserDao userDao1 = (IUserDao) cxt.getBean("userDao2");
        IUserDao userDao2 = (IUserDao) cxt.getBean("userDao2");

        System.out.println(userDao1);
        System.out.println(userDao2);
    }
}

10_IoC的注解配置-bean生命周期

目标

  • 能够使用@PostConstruct、@PreDestroy设置初始化、销毁方法

路径

  1. 使用@PostConstruct、@PreDestroy设置初始化、销毁方法

@PostConstruct、@PreDestroy注解介绍

@PostConstruct注解:

@Component
public class ClassName{
    @PostConstruct
    public void init() {
        //初始化方法
    }
}

@PreDestroy注解:

@Component
public class ClassName{
    @PreDestroy
    public void destory() {
        //销毁方法
    }
}

代码示例:

@Repository("userDao2")
@Scope("singleton")
//@Scope("prototype")
public class UserDaoImpl2 implements IUserDao {
    public UserDaoImpl2(){
        System.out.println("UserDaoImpl2构造方法...");
    }

    @PostConstruct
    public void init(){
        System.out.println("UserDaoImpl2 => 初始化方法");
    }

    @PreDestroy
    public void destroy(){
        System.out.println("UserDaoImpl2 => 销毁方法");
    }

    /**
     * 添加用户
     * @param user
     */
    @Override
    public void addUser(User user) {
        System.out.println("UserDao2 => addUser方法");
    }
}
public class UserDaoTest3 {
    @Test
    public void testBeanScope(){
        //加载配置类初始化容器
        ApplicationContext cxt = new AnnotationConfigApplicationContext(SpringConfig.class);

        //从容器中获取对象
        IUserDao userDao1 = (IUserDao) cxt.getBean("userDao2");

        IUserDao userDao2 = (IUserDao) cxt.getBean("userDao2");

        System.out.println(userDao1);
        System.out.println(userDao2);
    }
}

11_Spring整合Mybatis

目标

  • 能够使用Spring整合Mybatis

路径

  1. 准备工作
  2. 使用Spring整合Mybatis
  3. 优化Spring和Mybatis的整合

我们之前介绍过,spring可以整合其他框架融合自己的体系, 下面我们一起来学习下使用spring整合mybatis

Spring整合Mybatis步骤:

  1. 创建基于mybatis的项目
  2. 使用spring的IoC改造mybatis

准备工作

前期准备工作:

  1. 数据库
  2. 构造maven项目
  3. 导入坐标 [Mybatis、Mysql、Druid、Spring]
  4. Pojo类
  5. Dao层
  6. Service层
  7. 配置文件
  8. 工具类:SqlSessionUtil
  • 数据库:
create database spring_db;
use spring_db;
## 表
create table account(
	id int primary key auto_increment,
	name varchar(20),
	money double	
);
## 测试数据
insert into account values(null,'jack',1000),(null,'rose',1000);
  • 构造maven项目:

image-20220423221719120

  • 导入坐标
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.itheima</groupId>
    <artifactId>spring_demo2-mybatis</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- spring依赖 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
        <!--
           junit测试框架
        -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <!--
           mysql驱动
        -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.45</version>
        </dependency>
        <!--
            Druid
        -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.1</version>
        </dependency>
        <!--
            mybatis
        -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.3</version>
        </dependency>
    </dependencies>
</project>
  • Pojo类
public class Account {
    private Integer id;
    private String name;
    private Float money;

    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Float getMoney() {
        return money;
    }
    public void setMoney(Float money) {
        this.money = money;
    }
    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", money=" + money +
                '}';
    }
}

  • Dao层
public interface AccountDao {
    @Insert("insert into account(name,money)values(#{name},#{money})")
    void saveAccount(Account account);

    @Delete("delete from account where id = #{id} ")
    void deleteAccountById(Integer id);

    @Update("update account set name = #{name} , money = #{money} where id = #{id} ")
    void updateAccount(Account account);

    @Select("select id,name,money from account")
    List<Account> findAll();

    @Select("select id,name,money from account where id = #{id} ")
    Account findById(Integer id);
}
  • Service层
//接口
public interface IAccountService {
    /**
     * 添加用户
     * @param account
     */
    public void saveAccount(Account account);

    /**
     * 修改用户
     * @param account
     */
    public void updateAccount(Account account);
    
    /**
     * 删除用户
     * @param id
     */
    public void deleteAccount(Integer id);
    
    /**
     * 根据id查询用户
     * @param id
     * @return
     */
    public Account findById(Integer id);

    /**
     * 查询所有用户
     * @return
     */
    public List<Account> findAll();
}



//实现类
public class AccountServiceImpl implements IAccountService {
    @Override
    public void saveAccount(Account account) {
        SqlSession session = SqlSessionUtil.getSession();
        AccountDao accountDao = session.getMapper(AccountDao.class);
        accountDao.saveAccount(account);
        session.close();
    }

    @Override
    public void updateAccount(Account account) {
        SqlSession session = SqlSessionUtil.getSession();
        AccountDao accountDao = session.getMapper(AccountDao.class);
        accountDao.updateAccount(account);
        session.close();
    }

    @Override
    public void deleteAccount(Integer id) {
        SqlSession session = SqlSessionUtil.getSession();
        AccountDao accountDao = session.getMapper(AccountDao.class);
        accountDao.deleteAccountById(id);
        session.close();
    }

    @Override
    public Account findById(Integer id) {
        SqlSession session = SqlSessionUtil.getSession();
        AccountDao accountDao = session.getMapper(AccountDao.class);
        Account account = accountDao.findById(id);
        session.close();
        return account;
    }

    @Override
    public List<Account> findAll() {
        SqlSession session = SqlSessionUtil.getSession();
        AccountDao accountDao = session.getMapper(AccountDao.class);
        List<Account> list = accountDao.findAll();
        session.close();
        return list;
    }
}
  • 配置文件

    • 数据库配置
    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://127.0.0.1:3306/spring_db
    jdbc.username=root
    jdbc.password=itheima
    
    • mybatis配置文件
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <!-- 引入外部资源文件 -->
        <properties resource="db.properties"/>
        <typeAliases>
            <package name="com.itheima.pojo"/>
        </typeAliases>
        <environments default="mysql">
            <environment id="mysql">
                <transactionManager type="JDBC"></transactionManager>
                <dataSource type="POOLED">
                    <property name="driver" value="${jdbc.driver}"></property>
                    <property name="url" value="${jdbc.url}"></property>
                    <property name="username" value="${jdbc.username}"></property>
                    <property name="password" value="${jdbc.password}"></property>
                </dataSource>
            </environment>
        </environments>
        <mappers>
            <!-- 指定扫描的包 -->
            <package name="com.itheima.dao"></package>
        </mappers>
    </configuration>
    
  • 工具类

public class SqlSessionUtil {
    private static SqlSessionFactory factory;

    static {
        //实例化工厂建造类
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //读取核心配置文件
        try (InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml")) {
            //创建工厂对象
            factory = builder.build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取会话对象
     * @return 会话对象 : 自动提交事务
     */
    public static SqlSession getSession() {
        return factory.openSession(true);
    }

    /**
     * 获取会话对象
     * @param isAutoCommit 是否自动提交事务
     */
    public static SqlSession getSession(boolean isAutoCommit) {
        return factory.openSession(isAutoCommit);
    }

    /**
     * 提交事务并关闭session
     * @param session
     */
    public static void commitAndClose(SqlSession session) {
        if (session != null) {
            session.commit();
            session.close();
        }
    }

    /**
     * 回滚事务并关闭session
     * @param session
     */
    public static void rollbackAndClose(SqlSession session) {
        if (session != null) {
            session.rollback();
            session.close();
        }
    }
}

使用Spring整合Mybatis

spring改造mybatis的步骤:

  1. 新增mybatis配置类:MybatisConfig
  2. 新增spring配置类:SpringConfig
  3. 修改AccountServiceImpl类
  • 新增mybatis配置类
//Mybatis配置类
public class MybatisConfig {
    //SqlSessionFactoryBuilder -> SqlSessionFactory -> SqlSession -> AccountDao
    
    //将SqlSessionFactory放入到ioc容器
    @Bean("factory")
    public SqlSessionFactory getFactory() throws IOException {
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory factory = builder.build(inputStream);
        return factory;
    }

    //将SqlSession放到ioc容器中
    @Bean  //在方法上使用@Bean注解时:方法参数列表中声明的对象会自动从ioc容器中获取
    public SqlSession getSqlSession(SqlSessionFactory factory){
        SqlSession sqlSession = factory.openSession(true);
        return sqlSession;
    }

    //将accountDao放到ioc容器中
    @Bean("accountDao") //自动从ioc容器中获取SqlSession类型的bean对象
    public AccountDao getDao(SqlSession sqlSession){
        AccountDao accountDao = sqlSession.getMapper(AccountDao.class);
        return accountDao;
    }
}
  • 新增spring配置类
@Configuration
@ComponentScan("com.itheima")
@Import(MybatisConfig.class)
public class SpringConfig {
}
  • 修改AccountServiceImpl类
@Service("accountService")
public class AccountServiceImpl implements IAccountService {
    @Autowired  //自动注入
    private AccountDao accountDao;

    @Override
    public void saveAccount(Account account) {
        accountDao.saveAccount(account);
    }

    @Override
    public void updateAccount(Account account) {
        accountDao.updateAccount(account);
    }

    @Override
    public void deleteAccount(Integer id) {
        accountDao.deleteAccountById(id);
    }

    @Override
    public Account findById(Integer id) {
        Account account = accountDao.findById(id);
        return account;
    }

    @Override
    public List<Account> findAll() {
        List<Account> list = accountDao.findAll();
        return list;
    }
}

测试类:

public class AccountServiceTest {
    IAccountService accountService;

    @Before
    public void init(){
        //加载配置类初始化容器
        ApplicationContext cxt = new AnnotationConfigApplicationContext(SpringConfig.class);
        //从容器中获取对象
        accountService = (IAccountService) cxt.getBean("accountService");
    }

    @Test
    public void testFindAccountById(){
        Account account = accountService.findById(1);
        System.out.println(account);
    }
}

优化Spring和Mybatis的整合

优化spring和mybatis整合的步骤:

  1. 导入坐标
  2. 修改MybatisConfig类
  3. 修改SpringConfig类
  • 导入坐标
	<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.2.10.RELEASE</version>
    </dependency>

    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>1.3.0</version>
    </dependency>
  • 修改MybatisConfig类
//Mybatis配置类
public class MybatisConfig {
    /*
        SqlSessionFactoryBean (mybatis的spring整合包提供的类)
        1. 底层会提供 SqlSessionFactory
        2. 当开发者需要注入dao层bean的,此SqlSessionFactory会自动提供
            还可以设置dao层的扫描
     */
    @Bean
    public SqlSessionFactoryBean getSqlSessionFactoryBean(DataSource ds){
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        //设置pojo的包扫描
        //factoryBean.setTypeAliasesPackage("com.itheima.pojo");
        //设置连接池
        factoryBean.setDataSource(ds);

        return factoryBean;
    }

    //定义bean,返回MapperScannerConfigurer对象(mybatis的spring整合包提供的类)
    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer(){
        MapperScannerConfigurer msc = new MapperScannerConfigurer();
        //设置dao层的接口扫描
        msc.setBasePackage("com.itheima.dao");
        return msc;
    }
}
  • 修改SpringConfig类
@Configuration
@ComponentScan("com.itheima")
@PropertySource("classpath:db.properties")
@Import(MybatisConfig.class)
public class SpringConfig {
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;

    @Bean
    public DataSource getDataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(username);
        ds.setPassword(password);
        return ds;
    }
}

注意:连接池配置不能放在MybatisConfig类中(只有先创建好连接池对象,MybatisConfig类中才能使用)

  • 可以放在SpringConfig类中,或者另写一个配置类,但是要保证此配置类先于MybatisConfig加载

12_Spring整合Junit

目标

  • 能够使用Spring整合Junit

路径

  1. 测试类中存在的问题
  2. 解决问题的思路
  3. 涉及的知识点介绍
  4. 使用spring整合junit

测试类中存在的问题

在之前书写的测试类中,每个测试方法都有以下两行代码:

//加载配置初始化容器
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
或
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);    
//从容器中获取对象
IUserService userService = (IUserService)ac.getBean("userService"); 
  • 这两行代码如果不写的话:直接会提示空指针异常。(所以又不能轻易删掉)

解决问题的思路

解决思路:

  • 我们需要程序能自动帮我们创建容器。一旦程序能自动创建spring容器,我们就无须手动创建了,问题也就解决了。

我们都使用过junit,但是junit都无法知晓我们是否使用了spring框架,更不用说帮我们创建spring容器了。不过好在,junit给我们暴露了一个注解,可以让我们替换掉它的运行器。

在spring框架中提供了一个运行器,可以读取配置文件或注解配置类来创建容器。只需要告诉它配置类或配置文件在哪就行了。

涉及的知识点介绍

替换掉Junit的运行器:@RunWith

@RunWith(SpringJUnit4ClassRunner.class)//替换掉junit的运行器,换成可以初始化spring容器的运行器
public class 测试类{
}

加载SpringIoC容器:@ContextConfiguration

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {SpringConfig.class})//加载配置类
public class 测试类{
}
  • 属性:

    • class[] :用来指定配置类

    • value[] :用来指定xml配置文件的路径

      @ContextConfiguration(value = {"classpath:bean.xml"})
      

使用spring整合junit

使用spring整合junit的步骤:

  1. 导入坐标
  2. 在测试类上添加:@RunWith、@ContextConfiguration
<!-- 引入单元测试的jar包(需要在4.12及以上) --> 	
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>

<!-- 导入Spring整合junit的jar包 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.2.10.RELEASE</version>
    <!-- 注意:要保证Spring体系下的jar包的版本号相同  -->
</dependency>

测试类:

@RunWith(SpringJUnit4ClassRunner.class) //SpringJUnit4ClassRunner替代junit原生执行器
@ContextConfiguration(classes= SpringConfig.class) //加载注解配置类
//@ContextConfiguration(value="classpath:applicationContext.xml") //加载xml配置文件
public class AccountTest {
    @Autowired   //自动装配依赖
    IAccountService accountService;
    
    @Test
    public void testFindAccountById(){
        Account ac = accountService.findById(1);
        System.out.println(ac);
    }
    
}

标签:spring,Spring,void,public,user,day02,注解,class
From: https://www.cnblogs.com/-turing/p/17206355.html

相关文章

  • Spring-day03
    Spring-day0301_Spring的AOP概述目标了解AOP存在的意义及方式路径AOP介绍AOP作用AOP优势Spring中AOP的实现方式在前面我们提到:Spring技术的两大核心就是Ioc(......
  • Kuboard安装并部署springcloud微服务项目
    Kuboard安装并部署springcloud微服务项目Kuboard是一款k8s的管理界面,我认为它有页面美观(颜值即正义)、操作简洁、系统配置要求不高、对新手友好的特点。开发者认为他们......
  • Spring-初始Spring
    Spring1、简介Spring:春天:----给软件行业带来了春天2002年,首次推出了Spring框架的雏形:interface21框架2004年3月24号诞生RodJohnson,SpringFramework创始人,......
  • Spring-IOC理论浅析
    IOC理论最开始时业务实现:UserDao接口UserDaoImpl实现类UserService业务接口UserServiceImpl业务实现类在我们之前的业务中,用户的需求可能会影响我们原来的代码,我们......
  • Spring-第一个Spring程序
    1、HelloSpring1、第一个Spring项目创建Spring配置文件XXX.xml(标准名称:ApplicationContext.xml)<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="http://www.spri......
  • Spring-DI(依赖注入)及Bean的作用域
    DI(依赖注入)1、构造器注入前面已经说过了2、set方式注入【重点】依赖注入:Set注入依赖:bean对象的创建依赖于容器注入:bean对象中的所有属性,由容器来注入【环境......
  • Spring-Bean的自动装配
    Bean的自动装配自动装配是Spring满足bean依赖的一种方式Spring会在上下文中自动寻找,并自动给bean装配属性在Spring中有三种装配的方式在xml中显式的配置在java中显......
  • springboot打包时遇到的问题
    第一个问题是Failedtoexecutegoalorg.apache.maven.plugins:maven-resources-plugin:3.3.0:resources(default-resources)onproject   我的springboot版本......
  • 2.HelloSpring
    2.HelloSpring思考问题?Hello对象是谁创建的?Hello对象是由Spring设置的Hello对象的属性是怎么设置的?Hello对象的属性是Spring容器设置的这个过程就叫控制反转......
  • Spring:简述一下bean的生命周期吧?
    bean的生命周期是指它在ioc容器中从创建到销毁的整个过程。 <hr> 一、生命周期1、实例化,为对象分配内存。2、构造方法。3、属性注入,set注入。4......