Spring03_基于注解的IOC配置、IOC 案例
程序员文章站
2024-01-03 09:07:52
...
文章目录
第四章: 基于注解的IOC配置
注解配置 和 xml配置要实现的功能都是一样的,都是要降低程序之间的耦合,只是配置形式不一样
步骤:
第一步:在配置文件(bean.xml)中找到注解的位置:
使用注解进行开发,还需多一个AOP的jar包
配置文件:
导入的约束:在官网上找(使用的约束和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要扫描的包 ,配置所需的标签不是在beans约束中,而是在一个名称为context名称空间和约束中-->
<!-- 使用的约束和xml配置使用的约束不一样-->
<!-- 会找到该包进行扫描,找到对应的注解-->
<!-- base-package导入包的位置-->
<context:component-scan base-package="com.zy"/>
</beans>
第二步:在类上进行注解的定义
<!-- 曾经XML的配置: -->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl" scope="" init-method="" destroy-method="">
<property name="get方法" value="值" | ref="值"></property>
</bean>
(1)创建Bean对象放到容器中的注解:
-
他们的作用就
和在XML配置文件中编写一个<bean>标签实现的功能是一样的
-
@Component: 作用:用于把当前类对象存入spring容器中(是一下三个注解的父类)(默认调用该方法的构造方法创建) 属性: value:用于指定bean的id。当我们不写时,它的默认值是当前类名,且首字母改小写。 出现的位置: 在类上添加该注解 使用方法: 1: 在类上加 @Component 类的名称为id值(首字母字母小写) 2: 在类上加 @Component(value="id值") 3: 在类上加 @Component("id值") 使用于只有一个值的情况下
-
@Controller: 一般用在表现层 作用:是@Component注解的子标签,和其一样的作用,只不过是该标签常用于表现层 出现的位置: 在类上添加该注解
-
@Service: 一般用在业务层 作用:是@Component注解的子标签,和其一样的作用,只不过是该标签常用于表现层 出现的位置: 在类上添加该注解
-
@Repository : 一般用在持久层 作用:是@Component注解的子标签,和其一样的作用,只不过是该标签常用于表现层 出现的位置: 在类上添加该注解
(2) 用于注入数据的注解:
-
他们的作用和xml配置中的标签一样
-
Bean类型的注入
-
@Autowired: 作用:自动按照类型注入。只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功 如果ioc容器中没有任何bean的类型和要注入的变量类型匹配,则报错。 (告诉mybatis这个Bean属性是调用的哪个对象,mybatis会取容器中自己找该对象(mybatis先找,先根据类名找,先根据接口找,在根据属性名找)) 如果Ioc容器中有多个类型匹配时: 出现位置: 可以是变量上,也可以是方法上 细节: 在使用注解注入时,set方法就不是必须的了。 补充: @Autowired与@Autowired(required=true) 不允许该属性为空(默认值)(容器中必须有该对象) @Autowired(required=false) 允许该属性为空(容器中可以没有该属性的Bean对象)
-
mybatis根据提供的@Autowired标签找容器中的对象??(自动注入)
-
比如: 在一个成员变量(Bean变量)上面声明了 @Autowired
-
现在容器中有一下三个bean对象:
-
先根据IAccountDao接口找容器中的对象,找到两个实现类对象(AcountDao1 和 AcountDao2),在根据属性名找值,唯一确定的是AccountDao1的对象
-
-
-
- 下面代码:
- ```java
@Controller("dao")
public class AccountDao implements IAccountDao {
public AccountDao() {
}
public void saveAccount() {
System.out.println("账户已保存");
}
}
--------------------------------------------------------------------------------------------------------
@Controller("service")
public class AccountService implements IAccountService {
@Autowired
private final IAccountDao accountDao = null;
public IAccountDao getAccountDao() {
return accountDao;
}
public void saveAccountService() {
accountDao.saveAccount();
}
}
-----------------------------------------------------------------------------------------------------------
测试类:
public class text {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
AccountDao accountDao = (AccountDao)applicationContext.getBean("dao");
System.out.println(accountDao);
AccountService accountService = (AccountService)applicationContext.getBean("service");
System.out.println(accountService);
System.out.println(accountService.getAccountDao());
}
}
------------------------------------------------------------------------------------------------------------
运行结果:
aaa@qq.com
aaa@qq.com
aaa@qq.com
可以发现,accountService中的accountDao,就是容器中的AccountDao的Bean对象
AccountService类的AccountDao属性在标记上@Autowired的时候,自动在容器中获取对象
```
-
@Qualifier: 作用: 在按照类型注入的基础之上再按照名称注入。它在给类成员注入时不能单独使用。但是在给方法参数注入时可以(稍后我们讲) (该属性要使用容器中的对象:利用id实现指定) 解决@Autowired的缺陷 出现的位置: 可以是变量上,也可以是方法上 属性: value:用于指定注入bean的id。 注意: 在给类成员变量的时候,不能单独使用,要配合@Autowired 在给方法配置的时候,可以单独使用
-
public class AccountDao implements IAccountDao { public AccountDao() { } public void saveAccount() { System.out.println("账户已保存"); } } ------------------------------------------------------------------------------------------ 在容器中创建了两个AccountDao的对象 <bean id="dao1" class="com.zy.dao.impl.AccountDao"/> <bean id="dao2" class="com.zy.dao.impl.AccountDao"/> ----------------------------------------------------------------------------------------- @Controller("service") public class AccountService implements IAccountService { //指定出该属性要使用容器中的哪一个AcountDao对象(使用dao1) @Autowired @Qualifier(value = "dao1") private final IAccountDao accountDao = null; public IAccountDao getAccountDao() { return accountDao; } public void saveAccountService() { accountDao.saveAccount(); } } ------------------------------------------------------------------------------------------ 测试: public class text { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml"); AccountDao accountDao1 = (AccountDao)applicationContext.getBean("dao1"); AccountDao accountDao2 = (AccountDao)applicationContext.getBean("dao2"); System.out.println(accountDao1); System.out.println(accountDao2); AccountService accountService = (AccountService)applicationContext.getBean("service"); System.out.println(accountService); System.out.println(accountService.getAccountDao()); } } --------------------------------------------------------------------------------------------- 运行结果: com.zy.dao.impl.AccountDao@71d15f18 com.zy.dao.impl.AccountDao@17695df3 com.zy.serivce.impl.AccountService@6c9f5c0d com.zy.dao.impl.AccountDao@71d15f18 容器中的AccountService对象使用的是AccountDao的dao1对象
-
@Resource 作用: 直接按照bean的id注入。它可以独立使用 (在使用@Qualifier指定成员变量的时候,还需要用@Autowired太过于麻烦,直接用该标签进行代替) 出现的位置: 方法和属性上 属性: name:用于指定bean的id。(相当于@Qualifier中的value的值)
-
注意:
- 以上三个注入都
只能注入其他bean类型的数据,而基本类型和String类型无法使用上述注解实现。
- 另外,
集合类型的注入只能通过XML来实现
- 以上三个注入都
-
基本类型的注入
-
@Value 作用: 用于注入基本类型和String类型的数据 出现的位置: 基本类型的成员变量上 属性: value:用于指定数据的值。它可以使用spring中SpEL(也就是spring的el表达式) SpEL的写法:${表达式}
(3) 用于改变作用范围的
-
他们的作用就和<bean>上的scope属性一样
-
@Scope 作用:用于指定bean的作用范围 出现位置:类上 属性: value:指定范围的取值。常用取值:singleton(单例) prototype(多例)
-
(4) 和生命周期相关的注解
-
他们的作用就和在<bean>中使用init-method属性和destroy-methode属性的作用是一样的
-
@PreDestroy 作用: 用于指定销毁方法 使用的位置: 在方法上出现 @PostConstruct 作用: 用于指定初始化方法 使用的位置: 在方法上出现
-
案例: 基于xml文件的IOC案例
代码:
------------------------------------------------------------------------------------------------------------------------------------
domain中的实体类
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 +
'}';
}
}
--------------------------------------------------------------------------------------------------------------------------------
Dao持久层:
/**
* 账户的持久层接口
*/
public interface IAccountDao {
// 查询所有
List<Account> findAllAccount();
// 查询一个
Account findAccountById(Integer accountId);
// 保存
void saveAccount(Account account);
//更新
void updateAccount(Account account);
// 删除
void deleteAccount(Integer acccountId);
}
/**
* 账户的持久层实现类
*/
public class AccountDaoImpl implements IAccountDao {
//需要一个QueryRunner对象
private QueryRunner runner;
public void setRunner(QueryRunner runner) {
this.runner = runner;
}
public List<Account> findAllAccount() {
try{
return runner.query("select * from account",new BeanListHandler<Account>(Account.class));
}catch (Exception e) {
throw new RuntimeException(e);
}
}
public Account findAccountById(Integer accountId) {
try{
return runner.query("select * from account where id = ? ",new BeanHandler<Account>(Account.class),accountId);
}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 accountId) {
try{
runner.update("delete from account where id=?",accountId);
}catch (Exception e) {
throw new RuntimeException(e);
}
}
}
----------------------------------------------------------------------------------------------------------------------------
Service业务层:
/**
* 账户的业务层接口
*/
public interface IAccountService {
// 查询所有
List<Account> findAllAccount();
// 查询一个
Account findAccountById(Integer accountId);
// 保存
void saveAccount(Account account);
//更新
void updateAccount(Account account);
// 删除
void deleteAccount(Integer acccountId);
}
/**
* 账户的业务层实现类
*/
public class AccountServiceImpl implements IAccountService{
//需要一个IAccountDao的实现类对象
private IAccountDao accountDao;
public void setAccountDao(IAccountDao accountDao) {
this.accountDao = accountDao;
}
public List<Account> findAllAccount() {
return accountDao.findAllAccount();
}
public Account findAccountById(Integer accountId) {
return accountDao.findAccountById(accountId);
}
public void saveAccount(Account account) {
accountDao.saveAccount(account);
}
public void updateAccount(Account account) {
accountDao.updateAccount(account);
}
public void deleteAccount(Integer acccountId) {
accountDao.deleteAccount(acccountId);
}
}
---------------------------------------------------------------------------------------------------------------------
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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 配置Service -->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
<!-- 注入dao -->
<property name="accountDao" ref="accountDao"></property>
</bean>
<!--配置Dao对象-->
<bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
<!-- 注入QueryRunner -->
<property name="runner" ref="runner"></property>
</bean>
<!--配置QueryRunner-->
<bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
<!--注入数据源-->
<constructor-arg name="ds" ref="dataSource"></constructor-arg>
</bean>
<!-- 配置数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!--连接数据库的必备信息-->
<property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mybatis_damo1?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false"></property>
<property name="user" value="root"></property>
<property name="password" value="015718"></property>
</bean>
</beans>
案例: 基于注解的IOC案例
---------------------------------------------------------------------------------------------------------------------------------------
dao包:
/**
* 账户的实体类
*/
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;
}
public String toString() {
return "Account{" +
"id=" + id +
", name='" + name + '\'' +
", money=" + money +
'}';
}
}
----------------------------------------------------------------------------------------------------------------------------------------
Dao持久层:
/**
* 账户的持久层接口
*/
public interface IAccountDao {
// 查询所有
List<Account> findAllAccount();
// 查询一个
Account findAccountById(Integer accountId);
// 保存
void saveAccount(Account account);
//更新
void updateAccount(Account account);
// 删除
void deleteAccount(Integer acccountId);
}
/**
* 账户的持久层实现类
*/
@Repository("accountDao")
public class AccountDaoImpl implements IAccountDao {
@Autowired
private QueryRunner runner;
public List<Account> findAllAccount() {
try{
return runner.query("select * from account",new BeanListHandler<Account>(Account.class));
}catch (Exception e) {
throw new RuntimeException(e);
}
}
public Account findAccountById(Integer accountId) {
try{
return runner.query("select * from account where id = ? ",new BeanHandler<Account>(Account.class),accountId);
}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 accountId) {
try{
runner.update("delete from account where id=?",accountId);
}catch (Exception e) {
throw new RuntimeException(e);
}
}
}
----------------------------------------------------------------------------------------------------------------------------------------
Service业务层:
/**
* 账户的业务层接口
*/
public interface IAccountService {
// 查询所有
List<Account> findAllAccount();
// 查询一个
Account findAccountById(Integer accountId);
// 保存
void saveAccount(Account account);
//更新
void updateAccount(Account account);
// 删除
void deleteAccount(Integer acccountId);
}
/**
* 账户的业务层实现类
*/
public class AccountServiceImpl implements IAccountService{
//需要一个IAccountDao的实现类对象
@Autowired
private IAccountDao accountDao;
public void setAccountDao(IAccountDao accountDao) {
this.accountDao = accountDao;
}
public List<Account> findAllAccount() {
return accountDao.findAllAccount();
}
public Account findAccountById(Integer accountId) {
return accountDao.findAccountById(accountId);
}
public void saveAccount(Account account) {
accountDao.saveAccount(account);
}
public void updateAccount(Account account) {
accountDao.updateAccount(account);
}
public void deleteAccount(Integer acccountId) {
accountDao.deleteAccount(acccountId);
}
}
----------------------------------------------------------------------------------------------------------------------------------------
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">
<!-- 告知spring在创建容器时要扫描的包 -->
<context:component-scan base-package="com.itheima"></context:component-scan>
<!--配置QueryRunner-->
<bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
<!--注入数据源-->
<constructor-arg name="ds" ref="dataSource"></constructor-arg>
</bean>
<!-- 配置数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!--连接数据库的必备信息-->
<property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mybatis_damo1?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false"></property>
<property name="user" value="root"></property>
<property name="password" value="015718"></property>
</bean>
</beans>
----------------------------------------------------------------------------------------------------------------------------------------
在Dao接口的实现类上和Service接口的实现类上 ,其相应的成员变量添加上@Autowirde,在配置文件中只需要配置QueryRunner和ComboPooledDataSource对象