基于注解的IoC
常用的注解:
- @Component:
用于把当前类对象存入spring容器中,不写value属性时,value=当前类名且首字母小写。
service实现类:
@Component
public class AccountServiceImpl implements AccountService {
@Override
public void saveAccount() {
AccountDao accountDao = new AccountDaoImpl();
accountDao.saveAccount();
}
}
bean.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">
<!--创建容器时扫描的包-->
<context:component-scan base-package="SpringDemo2.service"></context:component-scan>
</beans>
@Controller(表现层)、@Service(业务层)、@Repository(持久层)它们三个与@Compontent作用一样而且更常用,是spring明确三层开发的注解。
-
自动按照类型注入:
@Autowired 自动按照类型注入。只要容器中有一个Bean对象类型和注入的变量匹配,就可以注入成功。书写位置:可以是成员变量、可以是方法。
@Qualifier 按照类型注入的基础上,再按照名称注入。在给类成员注入时不能单独使用(和AutoWired组合使用),在给参数注入时可以。
@Resource 直接按照bean的id注入。直接指定bean的id(属性为name而不是value)
@Value 用于注入基本类型和String类型。value属性用于指定值。可以使用spring中的el表达式({$表达式}) -
用于改变作用范围:
@Scope 用于指定bean的作用范围。属性:value:singleton(单例)、prototype(多例)。 -
声明周期相关:
@PreDestory 指定销毁方法
@PostConstruct 指定初始化方法
IoCxml配置crudDemo
maven依赖:
<dependencies>
<!--spring-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.4.RELEASE</version>
</dependency>
<!--dbutils-->
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.6</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<!--连接chi池-->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<!--单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
</dependency>
</dependencies>
实体类:
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 +
'}';
}
}
持久层接口:
public interface AccountDao {
/**
* 查询所有
* @return
*/
List<Account> findAllAccount();
/**
* 根据id查询
* @param id
* @return
*/
Account findAccountById(Integer id);
/**
* 添加
* @param account
*/
void saveAccount(Account account);
/**
* 更新
* @param account
*/
void updateAccount(Account account);
/**
* 删除
* @param id
*/
void deleteAccount(Integer id);
}
持久层实现类:
public class AccountDaoImpl implements AccountDao {
private QueryRunner runner;
public void setRunner(QueryRunner runner) {
this.runner = runner;
}
@Override
public List<Account> findAllAccount() {
try {
return runner.query("select * from account",new BeanListHandler<Account>(Account.class));
}catch (Exception e){
throw new RuntimeException(e);
}
}
@Override
public Account findAccountById(Integer id) {
try {
return runner.query("select * from account where id = ?",new BeanHandler<Account>(Account.class),id);
}catch (Exception e){
throw new RuntimeException(e);
}
}
@Override
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);
}
}
@Override
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);
}
}
@Override
public void deleteAccount(Integer id) {
try {
runner.update("delete from account where id = ?",id);
}catch (Exception e){
throw new RuntimeException(e);
}
}
}
业务层接口:
public interface AccountService {
/**
* 查询所有
* @return
*/
List<Account> findAllAccount();
/**
* 根据id查询
* @param id
* @return
*/
Account findAccountById(Integer id);
/**
* 添加
* @param account
*/
void saveAccount(Account account);
/**
* 更新
* @param account
*/
void updateAccount(Account account);
/**
* 删除
* @param id
*/
void deleteAccount(Integer id);
}
业务层实现类:
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
@Override
public List<Account> findAllAccount() {
return accountDao.findAllAccount();
}
@Override
public Account findAccountById(Integer id) {
return accountDao.findAccountById(id);
}
@Override
public void saveAccount(Account account) {
accountDao.saveAccount(account);
}
@Override
public void updateAccount(Account account) {
accountDao.updateAccount(account);
}
@Override
public void deleteAccount(Integer id) {
accountDao.deleteAccount(id);
}
public void setAccountDao(AccountDaoImpl accountDao) {
this.accountDao = accountDao;
}
}
测试类:
public class AccountServiceImplTest {
private AccountService accountService;
@Before
public void init(){
// 获取容器
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
// 得到对象
accountService = applicationContext.getBean("accountService", AccountService.class);
}
@Test
public void findAllAccount() {
System.out.println(accountService);
List<Account> all = accountService.findAllAccount();
for (Account account : all) {
System.out.println(account);
}
}
@Test
public void findAccountById() {
Account accountById = accountService.findAccountById(1);
System.out.println(accountById);
}
@Test
public void saveAccount() {
Account account = new Account();
account.setName("12312");
account.setMoney(1121);
accountService.saveAccount(account);
}
@Test
public void updateAccount() {
Account account = accountService.findAccountById(1);
account.setName("12312");
account.setMoney(1121);
accountService.updateAccount(account);
}
@Test
public void deleteAccount() {
accountService.deleteAccount(1);
}
}
修改上方xml配置为注解实现方式
修改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">
<!--spring在创建容器时要扫描的包-->
<context:component-scan base-package="SpringDemo2"></context:component-scan>
<!--配置QueryRunner对象-->
<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" scope="prototype">
<!--连接数据库的信息-->
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/springDemo?useSSL=false"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>
</beans>
在持久层实现类上添加@Repository("accountDao")
在业务层添加:@Service("accountService")
并且将注入的类的对象上添加 @AutoWride
(删除原有的set方法)
spring新注解
要想完全脱离xml文件,还需要下面的注解:
- @Configuration
表明当前类是一个测试类 - @ComponentScan:
用于通过注解指定spring在创建容器时要扫描的包。属性:value/basePackages作用是相同的,用于配置要扫描的包。 - @Bean
把当前方法的返回值作为bean对象存到Spring的IoC容器中。属性:name:用于指定bean的Id(不写时默认值为当前方法的名称)。当使用注解配置方法时,如果方法有参数,spring会去容器中查找有没有可以用的bean对象。 - @Scope
设置对象是单例还是多例。 - @Import
用于导入其它的配置类。有import注解的类是父配置类,导入的就是子配置类。 - @PropertySource
用于指定properties指定文件的名称和路径
spring于Junit的整合
在spring5.x中要求junit必须要在4.12以上
导入spring整合junit的jar包
<!--spring整合junit-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.4.RELEASE</version>
</dependency>
使用@RunWith(SpringJUnit4ClassRunner.class)
注解声明当前测试类为spring创建的。
使用@ContextConfiguration
来指定是基于xml的还是注解的。xml:locatiions:指定xml文件位置,加上classpath关键字,表示在类路径下。注解:classes:指定注解所在的位置: