暑期自学 Day 18 | Spring (四)

IoC 注解

使用注解创建对象之后,就不用像之前那样通过bean标签手动配置创建对象的属性了。
注解要写在需要注入的类或者成员方法前。
按作用分为四类:

创建对象

  • 和 bean 标签功能一样
    • @Component - 把当前对象存入 spring 容器
    • 属性:value: 指定 bean 的 id,默认值是当前类名,但首字母要小写
    • 衍生注解:使三层对象更加清晰,相当于@Component的子类
      • @Controller:表现层
      • @Service:业务层
      • @Repository:持久层

在 bean.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
        http://www.springframework.org/schema/context/spring-context.xsd">

<!-- 配置 component 注解所需的标签 -->
    <context:component-scan base-package="spring.selflearning"></context:component-scan>

</beans>

注入数据

  • 和 property 功能一样
  • @Autowired: 自动按照类型注入数据,只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就能注入成功。
    • 可以出现在变量上,也可以出现在方法上。
    • 此时无需set方法
  • @Qualifier:按照类型注入的基础上再按照名称注入。给类成员注入时不能单独使用,给方法参数注入时可以。
  • @Value:注入基本类型和String类型
  • 集合类型注入只能通过xml实现
  • 改变作用范围
    • 和 scope 一样
    • @Scope,取值可以是 singleton 或 prototype
  • 生命周期相关
    • 和 init-method 和 destroy-method 作用一样
    • @PreDestroy 销毁
    • @PostConstruct 初始化
    • 需要用 close() 方法释放容器
    • 只能销毁单例对象

Spring 的一些新注解

这些新注解功能和bean.xml中的一些属性功能相同,为的是取代bean.xml中的配置方式。

@Configuration

  • 表示当前类是个配置类
  • 当配置类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写。

如某个方法中使用ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);创建对象,那么无需在方法上使用@Configuration注解,因为Java会自动找到SpringConfiguration.class这个配置类创建对象。

AnnotationConfigApplicationContext方法中可以写多个配置类,用逗号分隔。

@ComponentScan

  • 指定spring创建容器时需要扫描的包;属性:basePackages
  • 功能和 <context:component-scan base-package="spring.selflearning"></context:component-scan> 一样。

@Bean

  • 把当前方法的返回值作为bean对象存入ioc容器中;属性:name,指定bean的id,不写时默认值为当前方法的名称
  • 如果bean注解有值,spring会去容器中查找是否有可用的bean对象,查找方式和AutoWired注解的功能一样

如给创建一个QueryRunner对象的方法添加注解:

    @Bean(name = "runner")
    @Scope("prototype")
    public QueryRunner createQueryRunner(DataSource dataSource) {
        return new QueryRunner(dataSource);
    }

@Import

  • 指定其他配置类的字节码
  • 使用Import注解之后的类就是父配置类,导入的是子配置类。此时创建对象时只需注解父类配置类即可。

PropertySource

  • 用于指定properties的位置
  • @Value:指定文件路径和名称,classpath,表示在类路径下
  • 在我实际使用中,发现Value注解无法正常读取properties配置文件,目前这个问题还没解决。附自己的代码:

父配置类:SpringConfiguration.java

@ComponentScan(basePackages = "spring.selflearning") // 属性是数组类型,如果需要扫描多个类则需加大括号
@Import(JdbcConfig.class)
@PropertySource("classpath:jdbcConfig.properties")
public class SpringConfiguration {}

子配置类:JdbcConfig.java

package config;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.sql.DataSource;

@Component("jdbcConfig")
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;

    public String getDriver() {
        return driver;
    }

    public String getUrl() {
        return url;
    }

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password;
    }

    @Bean(name = "runner")
    @Scope("prototype")
    public QueryRunner createQueryRunner(DataSource dataSource) {
        return new QueryRunner(dataSource);
    }

    @Bean(name = "dataSource")
    public DataSource createDataSource() {
        try {
            ComboPooledDataSource ds = new ComboPooledDataSource();
            ds.setDriverClass(driver);
            ds.setJdbcUrl(url);
            ds.setUser(username);
            ds.setPassword(password);
            return ds;
        }
        catch(Exception e) {
            throw  new RuntimeException(e);
        }
    }
}

jdbcConfig.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/eesy
jdbc.username=root
jdbc.password=1234

关于何时使用 xml,何时使用注解

实际上注解并不总是能减少配置过程中的代码量,如配置JDBC连接时。
配置注入的对象在别人写好的类中,那么使用xml更好;如果是自己写的类,直接在类中添加注解则更为方便。

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!