1. 基于注解的Ioc配置
Spring基于XML文件配置的形式为:
<bean id="accountService" class="dyliang.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"></property>
</bean>
<bean id="accountDao" class="dyliang.dao.impl.IAccountDaoImpl">
<property name="runner" ref="runner"></property>
</bean>
accountService和accountDao相对应的类实现代码为:
public class IAccountDaoImpl implements IAccountDao {
@Autowired
private QueryRunner runner;
public List<Account> findAll() {
try {
return runner.query("select * from account", new BeanListHandler<Account>(Account.class));
}catch (Exception e){
throw new RuntimeException(e);
}
}
public Account findById(Integer id) {
try {
return runner.query("select * from account where id=?", new BeanHandler<Account>(Account.class), id);
}catch (Exception e){
throw new RuntimeException(e);
}
}
public void saveAccount(Account account) {
try {
runner.update("insert into account(name,money)values(?,?)",account.getName(),account.getMoney());
}catch (Exception e){
throw new RuntimeException(e);
}
}
public void updateAccount(Account account) {
try {
runner.update("update account set name=?,money=? where id=?",account.getName(),account.getMoney(),account.getId());
}catch (Exception e){
throw new RuntimeException(e);
}
}
public void deleteAccount(Integer id) {
try {
runner.update("delete from account where id=?",id);
}catch (Exception e){
throw new RuntimeException(e);
}
}
}
public class AccountServiceImpl implements IAccountService {
@Autowired
private IAccountDao accountDao;
public List<Account> findAll() {
return accountDao.findAll();
}
public Account findById(Integer id) {
return accountDao.findById(id);
}
public void saveAccount(Account account) {
accountDao.saveAccount(account);
}
public void updateAccount(Account account) {
accountDao.updateAccount(account);
}
public void deleteAccount(Integer id) {
accountDao.deleteAccount(id);
}
}
spring中提供了注解@Component来配置资源的管理,对于
<bean id="accountService" class="dyliang.service.impl.AccountServiceImpl"></bean>
的功能相同实现只需要在对应的类上使用注解@Component,如下所示:
@Component
public class AccountServiceImpl implements IAccountService {
private IAccountDao accountDao;
public void setAccountDao(IAccountDao accountDao) {
this.accountDao = accountDao;
}
public List<Account> findAll() {
return accountDao.findAll();
}
使用了注解@Component后,虽然在bean.xml文件中不需要配置<bean>,但需要配置<context:component-scan>来告诉spring在创建Ioc容器时应该扫描哪些包,即使用@Component注解的类所在的包
<context:component-scan base-package="dyliang"></context:component-scan>
同时导入约束时需要多导入一个context名称空间下的约束,启用注解
<?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
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
最后编写测试类来执行单元测试
public class AccountTest {
@Test
public void testFindAll() {
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
IAccountService as = ac.getBean("accountService", IAccountService.class);
List<Account> accounts = as.findAll();
for (Account account : accounts) {
System.out.println(account);
}
}
@Test
public void testFindOne() {
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
IAccountService as = ac.getBean("accountService",IAccountService.class);
Account account = as.findById(1);
System.out.println(account);
}
@Test
public void testSave() {
Account account = new Account();
account.setName("test");
account.setMoney(12345f);
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
IAccountService as = ac.getBean("accountService",IAccountService.class);
as.saveAccount(account);
}
@Test
public void testUpdate() {
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
IAccountService as = ac.getBean("accountService",IAccountService.class);
Account account = as.findById(4);
account.setMoney(23456f);
as.updateAccount(account);
}
@Test
public void testDelete() {
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
IAccountService as = ac.getBean("accountService",IAccountService.class);
as.deleteAccount(4);
}
}
2. 常用注解
2.1 创建对象
- @Component:把资源让spring来管理,相当于在xml中配置一个bean。
- 属性value:指定bean的id,如果不指定value属性,默认bean的id是当前类首字母小写的类名
@Controller @Service @Repository和@Component的作用相同,但是语义更加的明确,显式的指明了注解适合使用的地方。同样可使用value属性来指定具体的名字,因为只有value,所以也可以省略不写。
-
@Controller:一般用于表现层
-
@Service:一般用于业务层
@Service("accountService") public class AccountServiceImpl implements IAccountService {}
-
@Repository:一般用于持久层
@Repository("accountDao") public class IAccountDaoImpl implements IAccountDao {}
2.2 注入数据
-
@Autowired:自动按照类型注入。当使用注解注入属性时,set方法可以省略。它只能注入其他bean类型。当有多个类型匹配时,使用要注入的对象变量名称作为bean的id,在spring容器查找,找到了可以注入成功;找不到就报错。使用方式如下:
@Service("accountService") public class AccountServiceImpl implements IAccountService { @Autowired private IAccountDao accountDao; }
当使用时,程序就会在Ioc容器中中找id为accountDao,对应的class为IAccountDao的对象。如果有,则自动注入,否则报错。
-
@Qualifier:在自动按照类型注入的基础之上,再按照Bean的id注入。它在给字段注入时不能独立使用,必须和@Autowired一起使用;但是给方法参数注入时,可以独立使用
- 属性value::指定bean的id
-
@Resource:直接按照Bean的id注入,它也能注入其他bean类型
- 属性name:指定bean的id
-
@Value:注入基本数据类型和String类型数据的值
- 属性value:用于指定值
2.3 改变作用范围
- @Scope:指定bean的作用范围
- 属性value:指定范围的值,取值:singleton、 prototype、 request 、session 、globalsession
2.4 生命周期
- @PostConstruct : 用于指定初始化方法
- @PreDestroy : 用于指定销毁方法
2.5 配置
-
@Configuration:用于指定当前类是一个spring配置类,当创建容器时会从该类上加载注解。获取容器时需要使用AnnotationApplicationContext(有@Configuration注解的类.class)
- 属性value:用于指定配置类的字节码
-
@ComponentScan:用于指定spring在初始化容器时要扫描的包。作用和在spring的xml配置文件中的
<context:component-scan base-package="dyliang"/>
一样- 属性basePackages:用于指定要扫描的包
-
@Bean:该注解只能写在方法上,表明使用此方法创建一个对象,并且放入spring容器
- 属性name:给当前@Bean注解方法创建的对象指定一个名称(即bean的id)
-
@PropertySource:用于加载.properties文件中的配置。例如我们配置数据源时,可以把连接数据库的信息写到properties配置文件中,就可以使用此注解指定properties配置文件的位置
- 属性value[]:用于指定properties文件位置。如果是在类路径下,需要写上classpath:
-
@Import:用于导入其他配置类,在引入其他配置类时,可以不用再写@Configuration注解
- 属性 value[]:用于指定其他配置类的字节码
public class JdbcConfig {
@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(name="runner")
@Scope("prototype")
public QueryRunner createQueryRunner(@Qualifier("ds") DataSource dataSource){
return new QueryRunner(dataSource);
}
@Bean(name="ds")
public DataSource createDataSource(){
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);
}
}
}
2.6 总结
基于XML配置 | 基于注解配置 | |
---|---|---|
Bean定义 | <bean id="..." class="..."/> |
@Component即衍生类@Repository、@Service、@Controller |
Bean名称 | 通过id或name指定 | @Component("…") |
Bean注入 | <property> 或者通过p命名空间 |
@Autowired按类型注入、@Qualifier按名称注入 |
生命过程、Bean作用范围 | init-method、destroy-method;范围scope属性 | @PostConstruct初始化、@PreDestroy销毁、@Scope设置作用范围 |
适合场景 | Bean来自第三方,使用其他Bean | Bean的实现类由用户自己开发 |
3. Spring整合Junit
-
导入坐标
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.2.5.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> </dependencies>
-
使用@RunWith注解替换原有运行器
@RunWith(SpringJUnit4ClassRunner.class) public class AccountTest {}
-
使用@ContextConfiguration指定spring配置文件的位置
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:bean.xml") public class AccountTest {}
-
使用@Autowired给测试类中的变量注入数据
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:bean.xml") public class AccountTest { @Autowired private IAccountService as; }
完整的使用:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:bean.xml")
public class AccountTest {
@Autowired
private IAccountService as;
@Test
public void testFindAll(){
List<Account> all = as.findAll();
for (Account account : all) {
System.out.println(account);
}
}
}
4. 基于完全注解的CURD
4.1 创建表
首先需要在数据库中创建表,并插入数据:
create table account(
id int primary key auto_increment,
name varchar(40),
money float
)character set utf8 collate utf8_general_ci;
insert into account(name,money) values('aaa',1000);
insert into account(name,money) values('bbb',1000);
insert into account(name,money) values('ccc',1000);
使用select查询:
mysql> select * from account;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | aaa | 1000 |
| 2 | bbb | 1000 |
| 3 | ccc | 1000 |
+----+------+-------+
3 rows in set (0.00 sec)
4.2 创建工程
创建Maven工程,然后导入需要的pom.xml中导入需要的坐标:
<?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>org.example</groupId>
<artifactId>SpringAllAnnotationAccount</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.20</version>
</dependency>
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
4.3 创建实体类
创建对应于表的实体类,并实现序列化接口:
public class Account implements Serializable {
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 +
'}';
}
}
4.4 持久层
public interface IAccountDao {
List<Account> findAll();
Account findById(Integer id);
void saveAccount(Account account);
void updateAccount(Account account);
void deleteAccount(Integer id);
}
@Repository("accountDao")
public class IAccountDaoImpl implements IAccountDao {
@Autowired
private QueryRunner runner;
public List<Account> findAll() {
try {
return runner.query("select * from account", new BeanListHandler<Account>(Account.class));
}catch (Exception e){
throw new RuntimeException(e);
}
}
public Account findById(Integer id) {
try {
return runner.query("select * from account where id=?", new BeanHandler<Account>(Account.class), id);
}catch (Exception e){
throw new RuntimeException(e);
}
}
public void saveAccount(Account account) {
try {
runner.update("insert into account(name,money)values(?,?)",account.getName(),account.getMoney());
}catch (Exception e){
throw new RuntimeException(e);
}
}
public void updateAccount(Account account) {
try {
runner.update("update account set name=?,money=? where id=?",account.getName(),account.getMoney(),account.getId());
}catch (Exception e){
throw new RuntimeException(e);
}
}
public void deleteAccount(Integer id) {
try {
runner.update("delete from account where id=?",id);
}catch (Exception e){
throw new RuntimeException(e);
}
}
}
4.5 业务层
public interface IAccountService {
List<Account> findAll();
Account findById(Integer id);
void saveAccount(Account account);
void updateAccount(Account account);
void deleteAccount(Integer id);
}
@Service("accountService")
public class AccountServiceImpl implements IAccountService {
@Autowired
private IAccountDao accountDao;
public List<Account> findAll() {
return accountDao.findAll();
}
public Account findById(Integer id) {
return accountDao.findById(id);
}
public void saveAccount(Account account) {
accountDao.saveAccount(account);
}
public void updateAccount(Account account) {
accountDao.updateAccount(account);
}
public void deleteAccount(Integer id) {
accountDao.deleteAccount(id);
}
}
4.6 配置类
public class JdbcConfig {
@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(name="runner")
@Scope("prototype")
public QueryRunner createQueryRunner(@Qualifier("ds") DataSource dataSource){
return new QueryRunner(dataSource);
}
@Bean(name="ds")
public DataSource createDataSource(){
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);
}
}
}
@ComponentScan("dyliang")
@Import(JdbcConfig.class)
@PropertySource("classpath:jdbcConfig.properties")
public class SpringConfiguration {
}
其中配置文件jdbcConfig.properties内容为:
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/sql_store?serverTimezone=GMT
jdbc.username=root
jdbc.password=1234
4.7 单元测试
最后,编写测试类并执行单元测试:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class)
public class AccountTest {
@Autowired
private IAccountService as = null;
@Test
public void testFindAll() {
List<Account> accounts = as.findAll();
for(Account account : accounts){
System.out.println(account);
}
}
@Test
public void testFindOne() {
Account account = as.findById(1);
System.out.println(account);
}
@Test
public void testSave() {
Account account = new Account();
account.setName("test anno");
account.setMoney(12345f);
as.saveAccount(account);
}
@Test
public void testUpdate() {
Account account = as.findById(4);
account.setMoney(23456f);
as.updateAccount(account);
}
@Test
public void testDelete() {
as.deleteAccount(4);
}
}
t> accounts = as.findAll();
for(Account account : accounts){
System.out.println(account);
}
}
@Test
public void testFindOne() {
Account account = as.findById(1);
System.out.println(account);
}
@Test
public void testSave() {
Account account = new Account();
account.setName("test anno");
account.setMoney(12345f);
as.saveAccount(account);
}
@Test
public void testUpdate() {
Account account = as.findById(4);
account.setMoney(23456f);
as.updateAccount(account);
}
@Test
public void testDelete() {
as.deleteAccount(4);
}
}
转载:https://blog.csdn.net/Forlogen/article/details/106946322