Spring学习第三弹。
spring-3-基于注解Ioc配置
1. 基于注解的Ioc配置
1. 环境搭建
在pom.xml中添加spring的依赖
1 2 3 4 5
| <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.2.RELEASE</version> </dependency>
|
Maven添加依赖时默认把spring的aop导入。
2. 创建service、dao、view类
修改bean.xml要扫描的包
1 2 3 4 5 6 7 8 9 10 11 12
| <?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" xmlns:conetext="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"> <context:component-scan base-package="top.tobing"></context:component-scan> </beans>
|
3. 使用注解
创建对象
- @Component(value=””):相当于一个xml配置中的一个bean
- @Controller(value=””):用于表现层
- @Service(value=””):用于业务层
- @Repository(value=””):用于持久层
后面三个注解是第一个注解的衍生,他们4个的作用及属性一模一样。只是提供了更为明确的语义
注入数据
- @Autowired:自动注入,不依赖setter,只能注入其他bean类型。当有多个类型匹配时,使用要注入的对象变量名称作为bean的id,在ioc容器中中寻找,没找到就报错
- @Qualifier(value=“”):结合第一个注解使用,可以用于指定bean的id
- @Resource(name=””):直接按照bean的id注入,只能注入其他bean类型
- @Value(value=””):注入基本数据类型和String类型
改变范围
- @Scope(value=“”):指定bean作用范围:单例(singleton)、多例(prototype)等。
生命周期(了解即可)
- @PostConstruct():指定初始化方法
- @PreDestroy():指定摧毁方法
创建对象相关注解
@Component(value=“”)用于创建对象,value指定id,value为空时使用类名首字母小写来作为默认id。Controller、Service、Repository三个注解可以混用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| @Service("userService01") public class UserServiceImpl implements UserService { private UserDao userDao ; public String toString() { return "ServiceImpl01"; } public void save() { userDao.save(); } }
@Service("userService02") public class UserServiceImpl1 implements UserService { private UserDao userDao ; public String toString() { return "ServiceImpl02"; } public void save() { userDao.save(); } }
|
1 2 3 4 5 6 7 8 9
| public class Client { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); Object obj = ac.getBean("userService02"); System.out.println(obj); } }
|
ServiceImpl02
注入数据相关注解
Dao层
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Repository("userDao01") public class UserDaoImpl implements UserDao { public void save() { System.out.println("Dao save!"); } }
@Repository("userDao02") public class UserDaoImpl1 implements UserDao { public void save() { System.out.println("Dao save!"); } }
|
Service层
1 2 3 4 5 6 7 8 9
| @Service("userService01") public class UserServiceImpl implements UserService { @Autowired() private UserDao userDao01 ; public void save() { userDao01.save(); } }
|
2. 基于xml的ioc案例
要求:使用spring的ioc对account表进行crud
1. 创建数据库
1 2 3 4 5 6 7 8 9 10 11
| CREATE DATABASE eesy; USE eesy; CREATE TABLE account( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(40), money FLOAT );
INSERT INTO account(NAME,money) VALUE("aaa",1000); INSERT INTO account(NAME,money) VALUE("bbb",3000); INSERT INTO account(NAME,money) VALUE("ccc",2000);
|
2. 创建Maven工程,导入依赖
- 创建maven工程
- 在pom.xml中导入要用到的依赖
- 数据库连接池c3p0
- dbutils
- mysql
- junit
- spring-context
pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.2.RELEASE</version> </dependency> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1.2</version> </dependency> <dependency> <groupId>commons-dbutils</groupId> <artifactId>commons-dbutils</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.0.2</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies>
|
3. 创建各层接口,实体类
实体类domain.Account–>account表
1 2 3 4 5 6
| public class Account implements Serializable { private Integer id; private String name; private Float money; }
|
持久层dao–>操作account
1 2 3 4 5 6 7 8
| public interface AccountDao { void save(Account account); void update(Account account); void delete(Integer id); List<Account> findAll(); Account findById(Integer id); }
|
dao.impl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| public class AccountDaoImpl implements AccountDao { private QueryRunner runner; public void setRunner(QueryRunner runner) { this.runner = runner; } public void save(Account account) { try { runner.update("insert into account(name,money) values(?,?)",account.getName(),account.getMoney()); } catch (SQLException e) { e.printStackTrace(); } } public void update(Account account) { try { runner.update("update account set name=? ,money=? where id = ?",account.getName(),account.getMoney(),account.getId()); } catch (SQLException e) { e.printStackTrace(); } } public void delete(Integer id) { try { runner.update("delete from account where id = ?",id); } catch (SQLException e) { e.printStackTrace(); } } public List<Account> findAll() { try { return runner.query("select * from account",new BeanListHandler<Account>(Account.class)); } catch (SQLException 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 (SQLException e) { throw new RuntimeException(e); } } }
|
业务层service–>调用持久层
1 2 3 4 5 6 7 8
| public interface AccountService { void save(Account account); void update(Account account); void delete(Integer id); List<Account> findAll(); Account findById(Integer id); }
|
4. 基于xml的bean注入
创建bean.xml
通过xml分别给各层的对象进行注入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="accountService" class="top.tobing.service.impl.AccountServiceImpl"> <property name="accountDao" ref="accountDao"></property> </bean> <bean id="accountDao" class="top.tobing.dao.impl.AccountDaoImpl"> <property name="runner" ref="runner"></property> </bean> <bean id="runner" class="org.apache.commons.dbutils.QueryRunner"> <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/eesy"></property> <property name="user" value="root"></property> <property name="password" value="root"></property> </bean> </beans>
|
5. 测试各层方法
- 使用ApplicationContext获取注入的对象
test.AccountServiceTest
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| public class AccountServiceTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml"); AccountService accountService = context.getBean("accountService",AccountService.class);
accountService.delete(4); } }
|
6. 原理图
3. 对以上案例进行基于注解的改造
1. 创建新工程
- 复制以上工程的所有代码:test,main,pom.xml
2. 更改bean.xml
将bean.xml中的约束改为注解的约束。
同时添加“spring创建容器时扫描的包”。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| <?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">
<context:component-scan base-package="top.tobing"></context:component-scan>
<bean id="runner" class="org.apache.commons.dbutils.QueryRunner"> <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/eesy"></property> <property name="user" value="root"></property> <property name="password" value="root"></property> </bean> </beans>
|
3. 添加注解
给持久层、业务层添加注解
1 2 3 4 5 6 7
| @Service("accountService") public class AccountServiceImpl implements AccountService { @Autowired private AccountDao accountDao; ... }
|
1 2 3 4 5 6 7
| @Repository("accountDao") public class AccountDaoImpl implements AccountDao { @Autowired private QueryRunner runner; .... }
|
4. 运行测试(略)
4. ioc案例存注解改造
0. 必须的新注解
Configuration:
1 2 3 4 5 6 7 8 9 10
| @Configuration public class SpringConfiguration { .... }
@Configuration public class JdbcConfiguration { ... }
|
ComponentScan:
1 2
| <context:component-scan base-package="top.tobing"></context:component-scan>
|
1 2 3 4 5
| @ComponentScan(value = "top.tobing") public class SpringConfiguration { .... }
|
Bean:
只能放在方法上,表明将该方法返回的对象放在spring的容器中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class JdbcConfiguration { ... @Bean("runner") @Scope("prototype") public QueryRunner getQueryRunner(DataSource dataSource){ .... } @Bean("dataSource") public DataSource getDataSource(){ .... } }
|
PropertySource:
1 2 3 4 5
| @PropertySource("classpath:jdbc.properties") public class JdbcConfiguration { ... }
|
@Import:
1 2 3 4 5 6
| @Import({JdbcConfiguration.class}) @ComponentScan(value = "top.tobing") public class SpringConfiguration {
}
|
1. 复制以上工程
2. 添加注解
config
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| @Configuration @Import({JdbcConfiguration.class}) @ComponentScan(value = "top.tobing") public class SpringConfiguration {
}
@Configuration @PropertySource("classpath:jdbc.properties") public class JdbcConfiguration {
@Value("${jdbc.username}") private String username; @Value("${jdbc.password}") private String password; @Value("${jdbc.driver}") private String driver; @Value("${jdbc.url}") private String url;
@Bean("runner") @Scope("prototype") public QueryRunner getQueryRunner(DataSource dataSource){ return new QueryRunner(dataSource); }
@Bean("dataSource") public DataSource getDataSource(){ try{ ComboPooledDataSource ds = new ComboPooledDataSource(); ds.setJdbcUrl("jdbc:mysql://localhost:3306/eesy"); ds.setDriverClass("com.mysql.jdbc.Driver"); ds.setUser("root"); ds.setPassword("root"); return ds; }catch (Exception e){ throw new RuntimeException(e); } } }
|
持久层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| @Repository("accountDao") public class AccountDaoImpl implements AccountDao { @Autowired private QueryRunner runner; public void setRunner(QueryRunner runner) { this.runner = runner; }
public void save(Account account) { try { runner.update("insert into account(name,money) values(?,?)",account.getName(),account.getMoney()); } catch (SQLException e) { e.printStackTrace(); } }
public void update(Account account) { try { runner.update("update account set name=? ,money=? where id = ?",account.getName(),account.getMoney(),account.getId()); } catch (SQLException e) { e.printStackTrace(); } }
public void delete(Integer id) { try { runner.update("delete from account where id = ?",id); } catch (SQLException e) { e.printStackTrace(); } }
public List<Account> findAll() { try { return runner.query("select * from account",new BeanListHandler<Account>(Account.class)); } catch (SQLException 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 (SQLException e) { throw new RuntimeException(e); } } }
|
业务层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| @Service("accountService") public class AccountServiceImpl implements AccountService { @Autowired private AccountDao accountDao; public void setAccountDao(AccountDao accountDao) { this.accountDao = accountDao; } public void save(Account account) { accountDao.save(account); } public void update(Account account) { accountDao.update(account); } public void delete(Integer id) { accountDao.delete(id); } public List<Account> findAll() { return accountDao.findAll(); } public Account findById(Integer id) { return accountDao.findById(id); } }
|
配置文件jdbc.properties
1 2 3 4 5
| jdbc.username=root jdbc.password=root jdbc.url=jdbc:mysql://localhost:3306/eesy jdbc.driver=com.mysql.jdbc.Driver
|
3. 测试
测试类
1 2 3 4 5 6 7 8 9 10 11 12
| public class AccountServiceTest { public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfiguration.class); AccountService accountService = context.getBean("accountService",AccountService.class); List<Account> accounts = accountService.findAll(); for (Account account : accounts) { System.out.println(account); } } }
|