Spring-IOC案例及单元测试

Spring-IOC案例的两种配置,xml 配置,和注解配置

一:使用 xml 配置链接数据库

<!--配置Service    -->
    <bean id="userService" class="huarangmeng.service.impl.UserServiceImpl">
        <!--注入Dao对象        -->
        <property name="userDao" ref="userDao"></property>
    </bean>

    <!--配置Dao    -->
    <bean id="userDao" class="huarangmeng.dao.impl.UserDaoImpl">
        <!--注入QueryRunner        -->
        <property name="runner" ref="runner"></property>
    </bean>

    <!--配置QueryRunner    -->
    <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
        <!--注入数据源        -->
        <constructor-arg name="ds" ref="dataSource"></constructor-arg>
    </bean>

    <!--配置数据源    -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!--链接数据库的必备信息        -->
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
        <property name="user" value="test"></property>
        <property name="password" value="a123456789"></property>
    </bean>

二:通过注解配置

QueryRunner为jar包中的字节码,无法直接通过注解配置

数据源同样

因而需要一个注解类来解决

/**
 * 该类是一个配置类,它的作用和bean.xml是一样的
 * spring中的新注解
 * @Configuration
 *      作用:指定当前类是一个配置类
 *      细节:当配置类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写
 * @ComponentScan
 *      作用:用于通过注解指定spring在创建容器时要扫描的包
 *      属性:
 *          value:他和basePackages的作用时一样的,都是用于指定创建容器时要扫描的包
 *              我们使用此注解就等同于在xml中配置了
 *              <context:component-scan base-package="huarangmeng"></context:component-scan>
 * @Bean
 *      作用:用于把当前方法的返回值作为bean对象存入spring的IOC容器中
 *      属性:
 *          name:用于指定 bean 的 id。默认值为 当前方法的名称.
 *      细节:当我们使用注解配置方法时,如果方法有参数,spring框架会去容器中查找是否有可用的bean对象
 *            查找的方式与 @Autowired注解的作用相同
 * @Import
 *      作用:用于导入其他的配置类
 *      属性:value:用于指定其他配置类的字节码。
 *      当我们使用 @Import注解后,有@Import注解的类就是父类配置,而导入的就是子配置类
 *
 * @PropertySource
 *      作用:用于指定properties文件的位置
 *      属性:
 *          value:指定文件的名称和路径
 *          关键字:classpath:表示类路径
 */
@Configuration
//@ComponentScan(basePackages = {"huarangmeng"}) 两种都可以
@ComponentScan("huarangmeng")
@Import(JdbcConfig.class)
@PropertySource("classpath:jdbc.properties")
public class SpringConfiguration {

    @Value("${jdbc.driver}")
    private String driver;

    @Value("${jdbc.url}")
    private String url;

    @Value("${jdbc.username}")
    private String username;

    @Value("${jdbc.password}")
    private String password;

    /**
     * 用于创建一个QueryRunner对象
     * @param dataSource
     * @return
     */
    @Bean(name = "runner")
    @Scope("prototype")
    public QueryRunner creteQueryRunner(DataSource dataSource){
        return new QueryRunner(dataSource);
    }

    /**
     * 创建数据源对象
     * @return
     */
    @Bean(name = "dataSource")
    public DataSource creteDataSource(){
        try{
            ComboPooledDataSource ds = new ComboPooledDataSource();
            ds.setDriverClass(driver);
            ds.setJdbcUrl(url);
            ds.setUser(username);
            ds.setPassword(password);
            return ds;
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }
}

举例说明 @Configuration 和 @ComponentScan,引入@Import 注解

  1. 当配置类作为 AnnotationConfigApplicationContext 对象创建的参数时,@Configuration注解可以不写

倘若有两个配置类,分别为 SpringConfiguration.class 和 JdbcConfig.class,直接作为参数,可不使用@Configuration注解,两个类可当作兄弟关系

//1.获取容器
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class,JdbcConfig.class);
//2.得到业务层对象
IUserService us = ac.getBean("userService", IUserService.class);
        
// JdbcConfig注解类
public class JdbcConfig {
}
// SpringConfiguration注解类
public class SpringConfiguration {
}
  1. 希望 SpringConfiguration.class 和 JdbcConfig.class 作为父子关系时

    //1.获取容器
    ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
    //2.得到业务层对象
    IUserService us = ac.getBean("userService", IUserService.class);
            
    // 第一种做法,给JdbcConfig类添加 @Configuration注解
    //给SpringConfiguration中添加扫描JdbcConfig的注解
    @Configuration
    public class JdbcConfig {
    }
    // SpringConfiguration注解类
    @ComponentScan("huarangmeng")
    public class SpringConfiguration {
    }
    		
    //第二种做法,给SpringConfiguration中添加@Import注解
    public class JdbcConfig {
    }
    // SpringConfiguration注解类
    @Import(JdbcConfig.class)
    public class SpringConfiguration {
    }
    

    三:Spring中的单元测试

    直接使用JUnit进行单元测试,存在问题,以下第一步和第二步,每个测试方法都要写,且要求测试同学有学过spring才会写出相应的代码

        @Test
        public void testFindAll(){
            //1.获取容器
    //        ApplicationContext ac = new ClassPathXmlApplicationContext("dao.xml");
    
            ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
            //2.得到业务层对象
            IUserService us = ac.getBean("userService", IUserService.class);
            //3.执行方法
            List<User> users = us.findAllUser();
            for (User user: users) {
                System.out.println(user);
            }
        }
    

    解决每个测试方法都要写前两步的问题

        private ApplicationContext ac;
    
        private IUserService us;
    
        @Before
        public void init(){
    //        1.获取容器
    //        ApplicationContext ac = new ClassPathXmlApplicationContext("dao.xml");
    
            ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
    //        2.得到业务层对象
            us = ac.getBean("userService", IUserService.class);
        }
    
        @Test
        public void testFindAll(){
            //3.执行方法
            List<User> users = us.findAllUser();
            for (User user: users) {
                System.out.println(user);
            }
        }
    

    仍然存在相应的代码需要写,则使用spring-test包解决问题

    为什么不能直接使用注解注入 IUserService,原因是 JUnit 下没有spring的IOC容器

    /**
     * 使用JUnit单元测试,测试我们的配置
     * spring整合junit配置
     *      1.导入spring整合junit的jar包
     *      2.使用Junit提供的一个注解把原有的main方法替换了,替换成spring提供的
     *          @RunWith
     *      3.告知spring 的运行期,spring的IOC容器创建时基于 xml 还是注解的,并说明位置
     *          @ContextConfiguration
     *              location:指定xml文件的位置,加上classpath关键字,表示在类路径下
     *              classes:指定注解类所在的位置
     *   当我们使用spring 5.X版本时,要求Junit的jar版本必须是4.12及以上
     */
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = SpringConfiguration.class)
    public class UserServiceTest {
    
        @Autowired
        private IUserService us;
    
        @Test
        public void testFindAll(){
            //3.执行方法
            List<User> users = us.findAllUser();
            for (User user: users) {
                System.out.println(user);
            }
        }
    }
    
posted @ 2020-09-16 18:15  花染梦  阅读(333)  评论(0编辑  收藏  举报