Spring注解开发以及Spring整合Junit

注解说明(只有在自己定义的类才可以用,用了注解来注入之后不需要原来的set方法了)
Spring原始注解
@Component 使用在类上用于实例化Bean
@Controller 使用在Web层类上用于实例化Bean
@Service 使用在Service层类上用于实例化Bean
@Repository 使用在Dao层类上用于实例化Bean
@Autowired 使用在字段上用于根据类型依赖注入
@Qualifier 结合@Autowired一起使用用于根据名称进行依赖注入
@Resource 相当于@Autowired+@Qualifier,按照名称进行注入
@Value 注入普通属性
@Scope 标注Bean的作用范围
@PostConstruct 使用在方法上标注该方法是Bean的初始化方法
@PreDestroy 使用在方法上标注该方法是Bean的销毁方法
@Transactional 在需要进行事务控制的类或是方法上开启事务

Spring新注解
使用上面的方式还不能完全代替xml配置文件,还需要使用注解替代的配置如下:
非自定义的Bean的配置: ;
加载properties文件的配置: context:property-placeholder ;
组件扫描的配置: context:component-scan ;
引用其他文件: 。
Spring后续版本新增注解如下:

注解说明
@Configuration 用于指定当前类是一个 Spring 配置类,当创建容器时会从该类上加载注解
@ComponentScan 用于指定Spring在初始化容器时要扫描的包。作用和在Spring的xml配置文件
中的<context:component-scan base-package=“com.hpe” />一样。
@Bean 使用在方法上,将该该法的返回值存储到Spring容器中,通常用于管理第三方
类(不是自己定义的类)的bean
@PropertySource 用于加载.properties文件中的配置
@Import 用于导入其他配置类

一、Spring注解开发

Spring是轻代码重配置的框架,配置比较繁琐,随着项目的扩大,配置会变得非常臃肿,影响开发效
率。为了解决这个问题,注解开发成为一种趋势,注解代替XML配置文件可以简化配置,提高开发效
率。

1.1、Spring原始注解

目的:代替Spring的 的配置

注解说明(只有在自己定义的类才可以用,用了注解来注入之后不需要原来的set方法了)
@Component 使用在类上用于实例化Bean
@Controller 使用在Web层类上用于实例化Bean
@Service 使用在Service层类上用于实例化Bean
@Repository 使用在Dao层类上用于实例化Bean
@Autowired 使用在字段上用于根据类型依赖注入
@Qualifier 结合@Autowired一起使用用于根据名称进行依赖注入
@Resource 相当于@Autowired+@Qualifier,按照名称进行注入
@Value 注入普通属性
@Scope 标注Bean的作用范围
@PostConstruct 使用在方法上标注该方法是Bean的初始化方法
@PreDestroy 使用在方法上标注该方法是Bean的销毁方法
@Transactional 在需要进行事务控制的类或是方法上开启事务

1.2、案例

该案例在《04_Spring_JdbcTemplate和声明式事务》基础上修改

1.2.1、修改Spring配置文件

使用注解进行开发时
需要在applicationContext.xml中配置组件扫描,作用是指定哪个包及其子包下的Bean需要进行
扫描以便识别使用注解配置的类、字段和方法;
配置文件中要开启事务的注解驱动<tx:annotation-driven />,同时指定事务管理器;
在使用原始注解情况下,第三方的类(不是自己定义的类)只能在XML中使用 标签配
置,无法使用上述注解进行配置。

<!-- 引入外部配置文件 -->
    <context:property-placeholder location="jdbc.properties" />
    <!-- 配置包扫描 -->
    <context:component-scan base-package="com.hpe" />

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" >
        <property name="driverClass" value="${jdbc.driver}" />
        <property name="jdbcUrl" value="${jdbc.url}" />
        <property name="user" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
    </bean>

    <bean id="jdbcTemplate1" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <bean id="jdbcTemplate2" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <!--<bean id="accountDao" class="com.hpe.dao.impl.AccountDaoImpl">-->
        <!--<property name="jdbcTemplate" ref="jdbcTemplate" />-->
    <!--</bean>-->

    <!--<bean id="accountService" class="com.hpe.service.impl.AccountServiceImpl">-->
        <!--<property name="accountDao" ref="accountDao" />-->
    <!--</bean>-->

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <!--&lt;!&ndash; 增强 &ndash;&gt;-->
    <!--<tx:advice id="txAdvice" transaction-manager="transactionManager">-->
        <!--<tx:attributes>-->
            <!--<tx:method name="*"/>-->
        <!--</tx:attributes>-->
    <!--</tx:advice>-->

    <!--&lt;!&ndash; 织入 &ndash;&gt;-->
    <!--<aop:config>-->
        <!--<aop:pointcut id="pt" expression="execution(* com.hpe.service.impl..*.*(..))" />-->
        <!--<aop:advisor advice-ref="txAdvice" pointcut-ref="pt" />-->
    <!--</aop:config>-->

    <!--事务的注解驱动-->
    <tx:annotation-driven transaction-manager="transactionManager" />

1.2.2、配置Dao

使用@Component或@Repository标识AccountDaoImpl需要Spring进行实例化。
使用@Autowired或者@Autowired+@Qulifier或者@Resource进行JdbcTemplate的注入。

//<bean id="accountDao" class="com.hpe.dao.impl.AccountDaoImpl" />
//@Scope(value = "singleton")
@Repository("accountDao")
public class AccountDaoImpl implements IAccountDao {
    //<property name="jdbcTemplate" ref="jdbcTemplate" />
    //按照类型注入,这里不需要set方法
    //@Autowired //单独使用根据类型注入 @Autowired+@Qualifier根据id进行注入
    //@Qualifier("jdbcTemplate2")
    @Resource(name = "jdbcTemplate2") //相当于@Autowired+@Qualifier
    private JdbcTemplate jdbcTemplate;

    //public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
    //    this.jdbcTemplate = jdbcTemplate;
    //}


    @Override
    public Account findById(Integer id) throws SQLException {
        String sql = "SELECT * FROM account WHERE id=?";
        Object[] params = {id};

        Account account = jdbcTemplate.queryForObject(sql, params, new BeanPropertyRowMapper<Account>(Account.class));
        return account;
    }

    @Override
    public void update(Account account) throws SQLException {
        String sql = "UPDATE account SET money=? WHERE id=?";
        Object[] params = {account.getMoney(), account.getId()};

        jdbcTemplate.update(sql, params);
    }

    @PostConstruct
    public void init() {
        System.out.println("初始化....");
    }

    @PreDestroy
    public void destory() {
        System.out.println("销毁....");
    }
}

1.2.3、配置Service

//相当于<bean id="accountService" class="com.hpe.service.impl.AccountServiceImpl"/>
@Service("accountService")
public class AccountServiceImpl implements IAccountService {
    //注入dao <property name="accountDao" ref="accountDao" />
    @Autowired//相当于上一行
    private IAccountDao accountDao;

//    public void setAccountDao(IAccountDao accountDao) {
//        this.accountDao = accountDao;
//    }

    @Override
    @Transactional//需要使用事务的代码前加这个注解(需要在配置文件里面<tx:annotation-driven transaction-manager="transactionManager"/>)
    public void transfer(Integer srcId, Integer dstId, Integer money) throws Exception {
        Account src = accountDao.findById(srcId);
        Account dst = accountDao.findById(dstId);

        if(src == null) {
            throw new RuntimeException("转出用户不存在");
        }

        if(dst == null) {
            throw new RuntimeException("转入用户不存在");
        }

        if(src.getMoney() < money) {
            throw new RuntimeException("转出账户余额不足");
        }

        src.setMoney(src.getMoney() - money);
        dst.setMoney(dst.getMoney() + money);

        accountDao.update(src);
        //int x = 1/0;
        accountDao.update(dst);
    }
}

1.2、Spring新注解

使用上面的方式还不能完全代替xml配置文件,还需要使用注解替代的配置如下:
非自定义的Bean的配置: ;
加载properties文件的配置: context:property-placeholder ;
组件扫描的配置: context:component-scan ;
引用其他文件: 。
Spring后续版本新增注解如下:

注解说明
@Configuration 用于指定当前类是一个 Spring 配置类,当创建容器时会从该类上加载注解
@ComponentScan 用于指定Spring在初始化容器时要扫描的包。作用和在Spring的xml配置文件
中的<context:component-scan base-package=“com.hpe” />一样。
@Bean 使用在方法上,将该该法的返回值存储到Spring容器中,通常用于管理第三方
类(不是自己定义的类)的bean
@PropertySource 用于加载.properties文件中的配置
@Import 用于导入其他配置类

1.2.1、Jdbc配置类

@Configuration
//用来引入外部文件
//<context:property-placeholder location="jdbc.properties" />
@PropertySource(value = "classpath:jdbc.properties")
public class JdbcConfig {
    @Value("${jdbc.driver}")
    private String drivename;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;


    @Bean("dataSource")//配置一个bean(配置那些不是自己定义的类)
    public DataSource dataSource() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass(drivename);
        dataSource.setJdbcUrl(url);
        dataSource.setUser(username);
        dataSource.setPassword(password);
        return dataSource;
    }
    @Bean
    public JdbcTemplate jdbcTemplate(@Qualifier("dataSource") DataSource dataSource){
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(dataSource);
        return jdbcTemplate;
    }
}

1.2.2、主配置类

@Configuration //声明当前类是一个配置类
//配置包扫描,找到注解的配置
//<context:component-scan base-package="com.hpe"/>
@ComponentScan(basePackages = "com.hpe")
//<!--配置注解驱动-->
//<tx:annotation-driven transaction-manager="transactionManager"/>
@EnableTransactionManagement
//将jdbc配置文件引入
@Import(JdbcConfig.class)
public class MainConfig {

    @Bean
    public DataSourceTransactionManager transactionManager(@Qualifier("dataSource") DataSource dataSource){
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource);
        return transactionManager;
    }
}

上面的内容也可以写在一个配置类中,这样是为了演示引入其他文件,写了两个配置类。使用上面的配置,在以后的开发中我们就可以完全抛弃XML配置了,这也是当前的主流,SpringBoot中就是这样做的。

二、Spring整合Junit
2.1、原始Junit测试Spring存在的问题
在测试类中,每个测试方法都有以下两行代码:

 //创建Spring容器
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        //获取代理对象
        IAccountService accountService = (IAccountService) context.getBean("accountService");

这两行代码的作用是获取容器,如果不写的话,直接会提示空指针异常。对于测试不友好。
2.2、希望达到的效果
只告诉测试类Spring的配置文件;
需要的Bean直接通过@Autowired注入。

2.3、步骤

  1. 导入相关Jar包,junit的jar包和spring-test的jar包;
    所有需要的jar包

  2. 使用@Runwith替换原来的运行时

  3. 使用@ContextConfiguration或@SpringJUnitConfig指定配置文件或配置类

  4. 使用@Autowired注入需要测试的对象

  5. 创建测试方法测试

//指定运行时
@RunWith(SpringJUnit4ClassRunner.class)
//指定Spring的配置文件或配置类
// @SpringJUnitConfig(locations = "classpath:applicationContext.xml")
@SpringJUnitConfig(MainConfig.class)
public class Mytset1 {
    @Autowired
    private IAccountService accountService;

    @Test
    public void tset1() throws Exception {
        accountService.transfer(1, 2, 100);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值