2、Spring基于注解的IOC配置、以及常用注解

1 案例:spring 基于xml的 IoC 的实现

在这里插入图片描述

package com.zzxx.dao;

import com.zzxx.domain.Account;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.List;

public class AccountDaoImpl implements AccountDAO {
    private JdbcTemplate jdbcTemplate;
    @Override
    public Account findById(int id) {
        String sql = "select * from account where id = ?";
        List<Account> list = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Account>(Account.class), id);
        return list.size() > 0?list.get(0):null;
    }

    @Override
    public void increaseMoney(int toId, double money) {
        String sql = "update account set money = money + ? where id = ?";
        jdbcTemplate.update(sql, money, toId);
    }

    @Override
    public void decreaseMoney(int fromId, double money) {
        String sql = "update account set money = money - ? where id = ?";
        jdbcTemplate.update(sql, money, fromId);
    }

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
}
package com.zzxx.domain;

public class Account {
    private Integer id;
    private Double money;

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", money=" + money +
                '}';
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Double getMoney() {
        return money;
    }

    public void setMoney(Double money) {
        this.money = money;
    }
}
package com.zzxx.service;

import com.zzxx.dao.AccountDAO;
import com.zzxx.domain.Account;

public class AccountServiceImpl implements AccountService {
    private AccountDAO accountDAO;
    @Override
    public Account selectById(int id) {
        return accountDAO.findById(id);
    }

    @Override
    public void transfer(int fromId, int toId, double money) {
        accountDAO.decreaseMoney(fromId, money);
        accountDAO.increaseMoney(toId, money);
    }

    public void setAccountDAO(AccountDAO accountDAO) {
        this.accountDAO = accountDAO;
    }
}
<?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 https://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 注册,管理 service对象 -->
    <bean id="accountService" class="com.zzxx.service.AccountServiceImpl">
        <property name="accountDAO" ref="accountDao"/>
    </bean>
    <!-- 管理dao对象 -->
    <bean id="accountDao" class="com.zzxx.dao.AccountDaoImpl">
        <property name="jdbcTemplate" ref="jdbcTemplate"/>
    </bean>
    <!-- 管理jdbcTemplate 对象 -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg name="dataSource" ref="dataSource"/>
    </bean>
    <!-- 管理DataSource对象 -->
    <!-- context 命名空间约束 -->
    <!-- property-placeholder: 加载外部的properties文件
            location:文件路径  [classpath:]类路径的前缀
     -->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driverName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
</beans>
package com.zzxx.test;

import com.zzxx.domain.Account;
import com.zzxx.service.AccountService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

// 模拟web层
public class WebTest {

    @Test
    public void selectAccount() {
        // 先获得service对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        AccountService accountService = ac.getBean(AccountService.class);
        // 模拟web层调用service层方法
        Account account = accountService.selectById(1);
        System.out.println(account);
    }
}

2 基于注解的 IOC 配置

2.1 明确

学习基于注解的 IOC 配置,⼤家脑海⾥⾸先得有⼀个认知,即注解配置和 xml 配置要实现的功能都是⼀样的,都是要降低程序间的耦合。只是配置的形式不⼀样。
关于实际的开发中到底使⽤ xml 还是注解,每家公司有着不同的使⽤习惯。所以这两种配置⽅式我们都需要掌握。

2.2 环境搭建

2.2.1 第⼀步:添加必备 jar 包到⼯程中。

注意:在基于注解的配置中,我们还要多添加⼀个 aop 的 jar 包。但是由于我们使⽤的是maven⼯程,在添加spring-context依赖时,⾃动添加了aop依赖,所以这⼀步可以省略。

2.2.2 第⼆步:使⽤@Component注解配置管理的资源

在这里插入图片描述

注意:当我们使⽤注解注⼊时,set ⽅法不⽤写

2.2.3 第三步:创建 spring 的 xml 配置⽂件并开启对注解的⽀持

注意:基于注解整合时,导⼊约束时需要多导⼊⼀个 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
 
https://www.springframework.org/schema/context/spring-context.xsd">
 <!-- 告知 spring 创建容器时要扫描的包 -->
 <context:component-scan base-package="com.zzxx"/>
 <!-- 配置 queryRunner 此处我们只注⼊了数据源,表明每条语句独⽴事务-->
 <bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">
 <constructor-arg name="ds" ref="dataSource"/>
 </bean>
 <!-- 配置数据源 -->
 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
 <property name="driverClass" value="com.mysql.cj.jdbc.Driver"/>
 <property name="jdbcUrl" value="jdbc:mysql:///spring"/>
 <property name="user" value="root"/>
 <property name="password" value="root"/>
 </bean>
</beans>

2.3 常⽤注解

2.3.1 ⽤于创建对象的

相当于:<bean id="" class="">

2.3.1.1 @Component
作⽤:
	把资源让 spring 来管理。相当于在 xml 中配置⼀个 bean。
属性:
	value:指定 bean 的 id。如果不指定 value 属性,
	默认 bean 的 id 是当前类的类名。⾸字⺟⼩写。
2.3.1.2 @Controller @Service @Repository
他们三个注解都是针对⼀个的衍⽣注解,他们的作⽤及属性都是⼀模⼀样的。

他们只不过是提供了更加明确的语义化。

		@Controller:⼀般⽤于表现层的注解。
		
		@Service:⼀般⽤于业务层的注解。
		
		@Repository:⼀般⽤于持久层的注解。

细节:如果注解中有且只有⼀个属性要赋值时,且名称是 value,value 在赋值是可以不写。

2.3.2 ⽤于注⼊数据的

相当于:

<property name="" ref="">
 <property name="" value="">
2.3.2.1 @Autowired

作⽤: ⾃动按照类型注⼊。当使⽤注解注⼊属性时,set ⽅法可以省略。它只能注⼊其他 bean 类型。当有多个类型匹配时,使⽤要注⼊的对象变量名称作为 bean 的 id,在 spring 容器查找,找到了也可以注⼊成功。找不到就报错。

2.3.2.2 @Qualifier
作⽤:
	在⾃动按照类型注⼊的基础之上,再按照 Bean 的 id 注⼊。它在给字段注⼊
	时不能独⽴使⽤,必须和 @Autowire ⼀起使⽤;但是给⽅法参数注⼊时,
	可以独⽴使⽤。
	
属性:
	value:指定 bean 的 id。
2.3.2.3 @Resource
作⽤:
	直接按照 Bean 的 id 注⼊。它也只能注⼊其他 bean 类型。
	
属性:
	name:指定 bean 的 id。
2.3.2.4 @Value
作⽤:
	注⼊基本数据类型和 String 类型数据的。
	
属性:
	value:⽤于指定值。

2.3.3 ⽤于改变作⽤范围的

相当于:<bean id="" class="" scope="">

2.3.3.1 @Scope
作⽤:
	指定 bean 的作⽤范围。
	
属性:
	value:指定范围的值。
	
	取值:singleton prototype request session globalsession

2.3.4 和⽣命周期相关的(了解)

相当于:<bean id="" class="" init-method="" destroy-method="" >

2.3.4.1 @PostConstruct
作⽤:
		⽤于指定初始化⽅法。
2.3.4.2 @PreDestroy

作⽤: ⽤于指定销毁⽅法。

2.3.5 关于 Spring 注解和 XML 的选择问题

注解的优势:
	配置简单,维护⽅便(我们找到类,就相当于找到了对应的配置)。
XML 的优势:
	修改时,不⽤改源码。不涉及重新编译和部署。

Spring 管理 Bean ⽅式的⽐较:
在这里插入图片描述

2.4 spring 管理对象细节

基于注解的spring IOC配置中,bean对象的特点和基于XML配置是⼀模⼀样的。

2.5 spring 的纯注解配置

写到此处,基于注解的 IOC 配置已经完成,但是⼤家都发现了⼀个问题:我们依然离不开 spring的 xml 配置⽂件,那么能不能不写这个 bean.xml,所有配置都⽤注解来实现呢?

2.5.1 待改造的问题

我们发现,之所以我们现在离不开 xml 配置⽂件,是因为我们有⼀句很关键的配置:
在这里插入图片描述
在这里插入图片描述

2.5.2 新注解说明

2.5.2.1 @Configuration
作⽤:
	⽤于指定当前类是⼀个 spring 配置类,当创建容器时会从该类上加载注解。
	获取容器时需要使⽤AnnotationApplicationContext(有@Configuration 
	注解的类.class)。
属性:
	value:⽤于指定配置类的字节码

在这里插入图片描述

2.5.2.2 @ComponentScan
作⽤:
	⽤于指定 spring 在初始化容器时要扫描的包。作⽤和在 spring 的 xml
	 配置⽂件中的: <context:component-scan base-package="com.zzxx"/>
	  是⼀样的。
属性:
	basePackages:⽤于指定要扫描的包。和该注解中的 value 属性作⽤⼀样。

示例代码:
在这里插入图片描述

2.5.2.3 @Bean
作⽤:
	该注解只能写在⽅法上,表明使⽤此⽅法创建⼀个对象,并且放
	⼊ spring 容器。
属性:
	name:给当前 @Bean 注解⽅法创建的对象指定⼀个名称(即 bean 的 id)。

示例代码:

/**
* 连接数据库的配置类
* @author bonnie
**/
public class JdbcConfig {
 /**
 * 创建⼀个数据源,并存⼊ spring 容器中
 * @return
 */
 @Bean(name = "dataSource")
 public DataSource createDataSource() {
 try {
 ComboPooledDataSource ds = new ComboPooledDataSource();
 ds.setUser("root");
 ds.setPassword("root");
 ds.setDriverClass("com.mysql.cj.jdbc.Driver");
 ds.setJdbcUrl("jdbc:mysql:///spring");
 return ds;
 } catch (Exception e) {
 throw new RuntimeException(e);
 }
 }
 /**
 * 创建⼀个 QueryRunner,并且也存⼊ spring 容器中
 * @param dataSource
 * @return
 */
 @Bean(name = "queryRunner")
 public QueryRunner createQueryRunner(DataSource dataSource) {
 return new QueryRunner(dataSource);
 }
}
2.5.2.4 @PropertySource
作⽤:
	⽤于加载 .properties ⽂件中的配置。例如我们配置数据源时,可以把连接
	数据库的信息写到 properties 配置⽂件中,就可以使⽤此注解指定
	 properties 配置⽂件的位置。
属性:
	value[]:⽤于指定 properties ⽂件位置。如果是在类路径下,
	需要写上 classpath:
/**
* 连接数据库的配置类
* @author bonnie
**/
@PropertySource("classpath:jdbc.properties")
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;
 /**
 * 创建⼀个数据源,并存⼊ spring 容器中
 * @return
 */
 @Bean(name = "dataSource")
 public DataSource createDataSource() {
 try {
 ComboPooledDataSource ds = new ComboPooledDataSource();
 ds.setUser(username);
 ds.setPassword(password);
 ds.setDriverClass(driver);
 ds.setJdbcUrl(url);
 return ds;
 } catch (Exception e) {
 throw new RuntimeException(e);
 }
 }
}

在这里插入图片描述

2.5.2.5 @Import
作⽤:
	⽤于导⼊其他配置类,在引⼊其他配置类时,可以不⽤再写 @Configuration
	 注解。当然,写上也没问题。
属性:
	value[]:⽤于指定其他配置类的字节码。

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值