Spring(二):IOC注解开发
文章目录
1. spring基于XML的CRUD案例
1.1 环境搭建
- 创建maven项目,导入坐标
<dependencies>
<!--springIOC相关-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!--spring整合Junit-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.26</version>
</dependency>
<!--druid连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.9</version>
</dependency>
<!--jdbcTemplate相关-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.0.RELEASE</version>
</dependency>
<!--junit测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
</dependency>
</dependencies>
- 数据库和实体类
public class Account {
private Integer accountId;
private Integer uid;
private Double money;
}
- dao层增删改查代码(接口为IAccountDao,这里省略不写)
package com.zmysna.dao.impl;
public class AccountDaoImpl implements IAccountDao {
private JdbcTemplate jdbcTemplate;
public void saveAccount(Account account) {
jdbcTemplate.update("INSERT INTO account values(?,?,?)",
account.getAccountId(), account.getUid(), account.getMoney());
}
public void updateAccount(Account account) {
jdbcTemplate.update("UPDATE account SET uid=?, money=? where accountId=?",
account.getUid(), account.getMoney(), account.getAccountId());
}
public Account findAccountById(int id) {
try {
return jdbcTemplate.queryForObject("select * from account where accountId = ?", new BeanPropertyRowMapper<>(Account.class), id);
} catch (DataAccessException e) {
e.printStackTrace();
return null;
}
}
public void deleteAccount(int id) {
jdbcTemplate.update("DELETE FROM account where accountId = ?", id);
}
}
- service层增删该查代码(接口为IAccountService,这里省略不写)
public class AccountServiceImpl implements IAccountService{
private IAccountDao accountDao;
public Account getAccountById(int accountId) {
Account accountById = accountDao.findAccountById(accountId);
return accountById;
}
public void updateAccount(Account account) {
accountDao.updateAccount(account);
}
public void deleteAccount(int accountId) {
accountDao.deleteAccount(accountId);
}
public void saveAccount(Account account){
accountDao.saveAccount(account);
}
}
1.2 spring容器配置,管理所有的java类
- jdbc信息
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf8
jdbc.username=root
jdbc.password=awsed2zx
jdbc.initialSize=3
jdbc.maxActive=50
- applicationContext.xml
<?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">
<!--加载jdbc配置文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--配置数据库连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!--配置jdbcTemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="dataSource" name="dataSource"></constructor-arg>
</bean>
<!--配置dao层-->
<bean id="accountDao" class="com.zmysna.dao.impl.AccountDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
<!--配置service层-->
<bean id="accountService" class="com.zmysna.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"></property>
</bean>
</beans>
1.3 测试
@Test
public void getAccountTest() {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
IAccountService accountService = ac.getBean("accountService", IAccountService.class);
System.out.println(accountService.getAccountById(1));
}
###2. spring常用注解介绍
2.1 创建对象加入容器
使用@Component(“bean名称”)可以配置对象的名称
以下四个注解的功能都是相同的, 为了更好的标识不同的java类使用不同的注解
@Component 用于工具类、其他组件
@Component
public class Account {}
@Repository 标识数据库访问层的组件
@Repository("accountDao") //创建dao层对象加入容器
public class AccountDaoImpl implements IAccountDao {}
@Service 标识业务逻辑层的组件
@Service("accountService") //创建service层对象加入容器
public class AccountServiceImpl implements IAccountService{}
@Controller 标识控制层的组件
2.2 依赖注入
-
@Autowired
- 从容器中找对象,给属性赋值。根据类型、名称去容器中找。
- 注入到属性上面
@Autowired private JdbcTemplate jdbcTemplate;
- 注入到方法形参中(方法名可以随意定义)
@Autowired public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; }
-
@Qualifier
- 结合 Autowired 使用,可以指定按照名称去容器找对象注入。
@Autowired @Qualifier("jdbcTemplate") //根据"jdbcTemplate"这个名称到容器中寻找对象 public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; }
-
@Value
- 给简单类型属性直接赋值/获取配置文件值@Value(“${key}”)
- 简单类型属性
@Value("11") //给简单类型属性赋值 private int i;
-
获取配置文件值
- 配置文件
jdbc.username=root
- 赋值
@Value("${jdbc.username}") private String username;
-
@Resource
从容器中找对象,给属性赋值。 根据名称、类型去容器中查找。和 Autowired 功能类似,查找对象的顺序是想查找名称,再查找类型,和Autowired相反。只能在 jdk1.5~1.8 使用, 不推荐使用。
####2.3 作用范围
@Scope:和bean标签中的scope属性功能相同
设置bean的作用范围,取值如下:
singleton:单例,默认值
prototype:多例
request:web项目中,将对象存入request域中
session: web项目中,将对象存入session域中
globalsession:web项目中,应用在集群环境中, 如果没有集群环境,相当域session
使用
@Component
// 指定对象是单例还是多例,默认是单例
//@Scope("singleton") // 默认值
@Scope("prototype") // 多例
public class Account {
…
}
2.4 生命周期和懒加载
@PostConstruct:用于指定初始化方法,相当于:<bean id="" class="" init-method=""/>
@PreDestroy:用于指定销毁方法:相当于<bean id="" class="" init-method="" destroy-method=""/>
@Lazy:懒加载,只能用于单例对象。
@Component
@Lazy //开启懒加载
public class Account {
public Account(){
System.out.println("1. 创建对象");
}
// 表示再创建对象之后执行
@PostConstruct
public void init_(){
System.out.println("2. 执行 init 初始化方法");
}
// 表示在销毁容器时候执行
@PreDestroy
public void destroy_(){
System.out.println("3. 执行 destroy 释放资源的方法,在关闭容器时候执行。");
}
}
2.5 配置文件信息注解
将配置文件中的信息也用注解表示,实现纯注解无配置开发。
@Configuration
用于指定当前类是一个 spring 配置类, 当创建容器时会从该类上加载注解。 获取容器时需要使用AnnotationApplicationContext(有@Configuration 注解的类.class)。
@ComponentScan
用于指定 spring 在初始化容器时要扫描的包。 作用和在 spring 的 xml 配置文件中的:<context:component-scan base-package=“com.itheima”/>是一样的。
@PropertySource
用于加载.properties 文件中的配置。例如我们配置数据源时,可以把连接数据库的信息写到 properties 配置文件中,就可以使用此注解指定 properties 配置文件的位置。
@Bean
该注解只能写在方法上,表明使用此方法创建一个对象,并且放入spring 容器
@Import
用于导入其他配置类,在引入其他配置类时,可以不用再写@Configuration 注解。当然,写上也没问题。
3 改造CRUD案例,实现纯注解开发
3.1 配置文件信息注解化
- xml配置文件类
package config;
//指定当前类为Spring配置类
@Configuration
//指定初始容器时扫描的包
@ComponentScan("com.zmysna")
//导入其他配置文件类
@Import(JdbcConfig.class)
public class SpringConfiguration {
}
-
JDBC注解配置
- 配置文件 jdbc.properties
jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf8 jdbc.username=root jdbc.password=awsed2zx jdbc.initialSize=3 jdbc.maxActive=50
- 配置类
package config; import com.alibaba.druid.pool.DruidDataSource; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.PropertySource; import org.springframework.jdbc.core.JdbcTemplate; import javax.sql.DataSource; //加载配置文件 @PropertySource(value = "classpath:jdbc.properties") public class JdbcConfig { //@${}读取配置文件信息 @Value("${jdbc.driverClassName}") private String driverClassName; @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String username; @Value("${jdbc.password}") private String password; //使用方法得到的DataSource对象放到容器中,指定名称为dataSource @Bean("dataSource") public DataSource createDataSource(){ DruidDataSource druidDataSource = new DruidDataSource(); druidDataSource.setUsername(username); druidDataSource.setPassword(password); druidDataSource.setUrl(url); druidDataSource.setDriverClassName(driverClassName); return druidDataSource; } //使用方法得到的DataSource对象放到容器中,指定名称为jdbcTemplate @Bean("jdbcTemplate") public JdbcTemplate createJdbcTemplate(@Qualifier("dataSource") DataSource dataSource){ return new JdbcTemplate(dataSource); } }
3.2 dao层
package com.zmysna.dao.impl;
//创建对象加入到容器中,对象名称是accountDao
@Repository("accountDao")
public class AccountDaoImpl implements IAccountDao {
//按照类型和名称自动注入jdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
...各种方法省略
}
3.3 service层
//创建对象加入到容器中,对象名称是accountService
@Service("accountService")
public class AccountServiceImpl implements IAccountService{
private IAccountDao accountDao;
//按照类型和名称自动注入accountDao(给accountDao赋值)
@Autowired
public void setAccountDao(IAccountDao accountDao) {
this.accountDao = accountDao;
}
}
3.4 测试
public class AnnoTest {
@Test
public void springAnnoTest() {
//通过AnnotationConfigApplicationContext加载注解配置类,创建容器。
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
IAccountService accountService = ac.getBean("accountService", IAccountService.class);
System.out.println(accountService.getAccountById(1));
}
}