Spring优雅的编写代码之基于注解的IOC

spring IOC的常用注解

  • 用于创建对象的

    • 他们的作用就和在XML中编写一个bean标签实现的功能是一致的

    • @Component

      • 作用:把当前类对象存入spring容器中
      • 属性:
        • value : 用于指定bean的id,当我们不写时,它的默认值是当前类名首字母小写
    • @Controller 一般用于表现层

    • @Service 一般用于业务层

    • @Repository 一般用于持久层

上述三个注解的作用和属性与`Component`是一模一样的,是spring框架为我们提供明确的三层使用注解,是我们的三层对象更清晰(优雅)
  • 用于注入数据的

    • 和XML配置文件中bean写property标签是一致的
    • @Autowired
      • 作用:自动按照类型注入.只要容器中有唯一一个bean对象类型和要注入的变量类型匹配,就可以注入成功,如果IOC容器中有多个匹配时,会根据变量名去匹配IOC容器(map结构)中的key(id)
      • 出现位置:
        • 可以是变量上,也可以是方法上(常用)
      • 细节: 使用注解时,set方法就不是必须的了
    • @Qualifier
      • 作用: 在按照变量类型中注入的基础上再按照变量名注入.
      • 细节: 再给类成员注入时不能单独使用,但是在给方法参数注入时可以单独使用
      • 属性
        • value: 用于指定注入bean的id
    • @Resource
      • 作用: 直接按照id注入
      • 属性:
        • name: 要注入值的id
    • 以上三种注解只能注入其他bean类型数据,而基本类型和String类型无法用上述注解实现,另外集合类型的注入只能通过XML实现
    • @Value
      • 作用: 用于注入指定数据的值.可以使用spring的SpEL(spring表达式)
        • SpEL写法 ${表达式}
  • 用于改变作用范围的

    • 和bean标签中使用scope属性的功能一致
    • @Scope
      • 作用:用于指定bean作用范围
      • 属性:
        • value
          • singleton 单例(默认值)
          • prototype 多例
      • 出现位置: 类上
  • 和生命周期相关的(了解即可)

    • 和bean标签中init-methoddestory-method的功能一致
    • @PreDestory
      • 作用: 用于指定销毁方法
    • @PostConstruct
      • 作用: 用于指定初始化方法
    • 出现位置: 方法上

案例使用XML方式实现表单的CRUD操作

采用dbutils,c3p0连接池,junit单元测试

  • bean.xml配置如下
  • 采用xml方式需要在Service和dao添加set方法
<?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.henu.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao" />
    </bean>
    <!--配置Dao对象-->
    <bean id="accountDao" class="com.henu.dao.impl.IAccountDaoImpl">
        <!--注入QuereyRunner-->
        <property name="runner" ref="runner"/>
    </bean>
    <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
        <!--注入数据源-->
        <constructor-arg name="ds" ref="dataSource"/>
    </bean>
    <!--配置数据源-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!--连接数据库的信息-->
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/springioc"/>
        <property name="user" value="root"/>
        <property name="password" value="gyg06103234"/>
    </bean>
</beans>

QueryRunner

核心类

  • QueryRunner(DataSource ds); 传入参数为连接池
  • pdate(String sql, Object… params) ; 执行insert update delete操作
  • query(String sql, ResultSetHandler rsh, Object… params) ; 执行 select操作

ResultSetHandler

结果集处理类

8JVel4.png

改造上述案例,使用纯注解方式实现

修改bean.xml约束:

<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 https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <context:annotation-config/>
  • 去掉Service和dao的注解

    • 删除Service中dao的set方法以及dao中QueryRunner的set方法

    • 在类名上分别添加@Service(accountService)注解和@Repository("accountDao")注解

    • 分别在两个成员变量上加入@AutoWrite注解即可,因为ioc容器中只存在唯一的对应对象

  • 去掉所有注解

    • Configuration 指定当前类是一个配置类
      • 当该类作为AnnotationConfigApplicationContext的参数时可以不加此注解
      • 作为参数就不用指定扫描范围,不作为参数就要指定扫描范围
    • ComponentScan指定扫描包的范围
      • 默认属性valuebasePackage任选一
      • 数组类型的注解,如果只有一个值,可以去掉大括号
    • Bean 把当前方法的返回值作为bean对象存入ioc容器中
      • name:用于指定bean的id
        • 默认值为当前方法的名称
      • 当使用@Bean注解配置方法时,如果有参数时,spring会按照Autowired的方式查找ioc容器中是否有唯一的对应变量的bean对象
    • import用于导入其他的配置类
      • value其他配置类字节码文件数组
      • 把其他的配置类都加入到主配置类
        • 只用加载主配置类,就可以加载所有配置类
    • PropertySource导入配置文件
      • value:指定文件的名称和路径
      • classpath:指定类路径下

spring 和 Junit整合

  • 导入spring-test依赖
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-test</artifactId>
	<version>5.0.2.RELEASE</version>
</dependency>
  • 使用Junit提供的注解把原有的main方法替换成spring提供的main方法
@RunWith(SpringJUnit4ClassRunner.class)
  • 告知spring的运行器,spring和ioc的创建是基于注解还是xml,并且说明位置
    • locations:指定xml文件位置,加上classpath关键字,表示在类路径下
    • classes:指定注解类所在的位置
@ContextConfiguration(classes = SpringConfiguration.class)
  • 当使用spring5.x版本的时候,要求Junit的版本必须是4.12及以上