Skip to content

Spring教程 - 5 IoC容器 - 基于注解配置(2)

继续基于注解配置。


5.5 全注解开发

在上面基于注解的配置,一开始还是创建了一个 bean.xml ,然后开启了注解配置。

其实我们可以使用全注解开发,这个 XML 文件都可以去掉。

一般在项目中,我们会创建一个配置类,在这个配置类上通过相关的注解,来启用 Spring 注解配置,从而替换 XML,实现全注解开发。


举个栗子:

首先将 bean.xml 都删掉。

然后在指定的包下创建一个类,一般都叫 config 包,例如 com.foooor.hellospring.config.SpringConfig.java,名称自定义。

java
package com.foooor.hellospring.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration  // 配置类
@ComponentScan("com.foooor.hellospring")  // 开启组件扫描,并指定扫描的包
public class SpringConfig {
}
  • 在上面的配置类,使用 @Configuration 注解标识这是一个配置类。
  • 然后使用 @ComponentScan 注解开启组件扫,并指定扫描的包。

接下来就可以测试了:

java
package com.foooor.hellospring;

import com.foooor.hellospring.config.SpringConfig;
import com.foooor.hellospring.controller.UserController;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * 测试类
 */
public class UserTest {

    @Test
    public void testUserService() {
        // 加载配置类
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        UserController userController = context.getBean(UserController.class);
        userController.getUser();
    }
}
  • 在测试类中,要使用 AnnotationConfigApplicationContext 加载配置类,然后就可以获取 bean 了。

当然,还是那句话,这里只是测试,在实际的开发中,这些代码都是不需要的。


5.6 @Bean注解

在使用 XML 配置的时候,我们可以在 XML 中,通过类的全路径,使用 <bean> 标签配置 bean,不管这个类是我们定义的,还是第三方的。

但是在使用注解配置的时候,如果是我们自己定义的类,直接在类上添加 @Component@Controller@Service@Repository 注解就可以了。

如果是第三方的类呢?我们又不能修改别人的类,添加注解。

那就需要使用 @Bean 注解,可以在配置类中,通过 @Bean 注解,创建第三方 bean 实例。

举个栗子:

java
package com.foooor.hellospring.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

@Configuration  // 配置类
@ComponentScan("com.foooor.hellospring")  // 开启组件扫描,并指定扫描的包
public class SpringConfig {

    @Bean
    public DataSource dataSource() {
        DruidDataSource ds = new DruidDataSource();
        ds.setUrl("jdbc:mysql://localhost:3306/foooor_db?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true");
        ds.setUsername("root");
        ds.setPassword("123456");
        return ds;
    }

}
  • 上面在配置类中,通过 @Bean 注解和方法来注册第三方的 Bean,方法名就是 bean 的 id,方法返回的对象就交由 Spring Ioc容器来管理。

还可以通过name属性,手动指定 bean 的 id :

java
@Bean(name = "dataSource")

一般情况下,我们会有一个主配置类,在主配置类上添加 @ComponentScan 注解,配置组件的扫描。但是如果要配置的 bean 很多,还可以再创建配置类,添加 @Configuration 注解进行配置,相当于有多个 XML 配置文件。

5.7 全注解获取数据库数据

在基于 XML 的配置中,我们引入外部属性文件 jdbc.properties 配置文件,然后基于配置文件中的配置创建数据源。最后实现从数据库获取数据。

下面使用注解的方式,实现这个功能。

1 引入依赖

和前面 XML 中的一致。

首先在项目的 pom.xml 中引入 MySQL 数据源和 druid 连接池的依赖:

xml
<!-- 引入mysql驱动依赖,用于连接mysql数据库 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.33</version>
</dependency>

<!-- 引入druid依赖,提供数据库连接池 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.27</version>
</dependency>

2 创建外部属性文件

和前面 XML 中的一致。

resources 目录下创建 jdbc.properties 配置文件,在配置文件中配置数据库相关的连接信息:

properties
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/foooor_db?useSSL=false&serverTimezone=UTC
jdbc.username=root
jdbc.password=123456
  • 这里要准备一下数据库,以及数据库中的表和数据。

3 创建配置类

我们可以在上面创建的 SpringConfig 配置类中进行配置。也可以再单独创建一个配置类。随你喜欢。

我这里就在SpringConfig类中配置了:

java
package com.foooor.hellospring.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

import javax.sql.DataSource;

@Configuration  // 配置类
@ComponentScan("com.foooor.hellospring")  // 开启组件扫描,并指定扫描的包
@PropertySource("classpath:jdbc.properties")  // 加载外部配置文件
public class SpringConfig {

    @Value("${jdbc.driver}")  // 读取从配置文件注入的属性值。
    private String driver;

    @Value("${jdbc.url}")
    private String url;

    @Value("${jdbc.username}")
    private String username;

    @Value("${jdbc.password}")
    private String password;

    @Bean
    public DataSource dataSource() {
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(username);
        ds.setPassword(password);
        return ds;
    }
}
  • 在类上添加 @PropertySource 注解,用户与加载外部的配置文件。
  • 然后使用 @Value 注解可以读取配置文件中的属性值。

如果有多个配置文件,还可以加载多个配置文件。

java
@PropertySource({
    "classpath:jdbc.properties",
    "classpath:redis.properties"
})

4 测试

编写测试类测试一下,获取数据源 bean 实例,然后获取数据库连接,就可以执行 SQL 获取数据了。

如下:

java
package com.foooor.hellospring;

import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * 测试类
 */
public class DataSourceTest {

    @Test
    public void testDataSource() {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        DataSource dataSource = context.getBean(DataSource.class);

        // 2. 获取连接
        try (Connection conn = dataSource.getConnection()) {
            Statement stmt = conn.createStatement();
            ResultSet rs = stmt.executeQuery("SELECT * FROM tb_user");

            while (rs.next()) {
                System.out.println(rs.getString("username"));
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

}
  • 数据库中是准备了表 tb_user ,并且有 username 字段,这里你可以在数据库中创建相应的表和字段。
  • 然后通过上面的测试代码可以获取到 tb_user 表中所有的数据,并打印 username 字段的值。

5.8 配置类说明

在上面,在配置类上添加了 @PropertySource 注解:

java
@Configuration  // 配置类
@ComponentScan("com.foooor.hellospring")  // 开启组件扫描,并指定扫描的包
@PropertySource("classpath:jdbc.properties")  // 加载外部配置文件
public class SpringConfig {
    // ...
}

其实此时只要是 Spring IoC 容器中的 Bean 都可以通过 @Value("${jdbc.username}") 的方式获取外部属性文件中的属性的,不只是局限于配置类中。


所以我完全可以创建一个数据类,添加 @Component 注解,然后就可以读取到配置文件中的属性了:

例如:JdbcConfig.java

java
package com.foooor.hellospring.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
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;

    // ...getter and setter
}
  • @Component 注解就是将 bean 交由 Spring 管理,就可以获取配置文件中的属性了。

那么在 配置类中,完全也可以获取到 JdbcConfig 的 bean。

java
package com.foooor.hellospring.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import javax.sql.DataSource;

@Configuration  // 配置类
@ComponentScan("com.foooor.hellospring")  // 开启组件扫描,并指定扫描的包
@PropertySource("classpath:jdbc.properties")  // 加载外部配置文件
public class SpringConfig {

    @Autowired
    private JdbcConfig jdbcConfig;

    @Bean
    public DataSource dataSource() {
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(jdbcConfig.getDriver());
        ds.setUrl(jdbcConfig.getUrl());
        ds.setUsername(jdbcConfig.getUsername());
        ds.setPassword(jdbcConfig.getPassword());
        return ds;
    }
}
  • 所以上面也可以获取到 JdbcConfig 的 bean 和其中的值,完全没毛病。
内容未完......