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>
<!--<!– 增强 –>-->
<!--<tx:advice id="txAdvice" transaction-manager="transactionManager">-->
<!--<tx:attributes>-->
<!--<tx:method name="*"/>-->
<!--</tx:attributes>-->
<!--</tx:advice>-->
<!--<!– 织入 –>-->
<!--<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、步骤
-
导入相关Jar包,junit的jar包和spring-test的jar包;
所有需要的jar包 -
使用@Runwith替换原来的运行时
-
使用@ContextConfiguration或@SpringJUnitConfig指定配置文件或配置类
-
使用@Autowired注入需要测试的对象
-
创建测试方法测试
//指定运行时
@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);
}
}