Spring - 组件注册(一)

组件注册

@Configuration@Bean

  • Spring 中配置类就相当于配置文件
import cn.lwjppz.entites.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 配置类 == 配置文件
 */

@Configuration  // 告诉 Spring 这是一个配置类
public class MainConfig {

    /**
     * 给容器注册一个 Bean ,类型为返回值类型,id默认使用方法名作为id
     * 也可给@Bean中传入value参数自定义id
     * @return user实例
     */
//    @Bean("user01")
    @Bean
    public User user() {
        return new User(1, "lwjppz", 20);
    }
}
  • 测试类
import cn.lwjppz.config.MainConfig;
import cn.lwjppz.entites.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MainTest {
    @Test
    public void test() {
        ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
        User user = context.getBean(User.class);
        System.out.println(user);

        String[] names = context.getBeanNamesForType(User.class);
        for (String name : names) {
            System.out.println(name);
        }
    }
}
  • 测试结果 hix75SsOybTElNJ

@ComponentScan - 自动扫描组件&指定扫描规则

  • 新建UserController、UserDao、UserService,分别加上@Controller,@Repository,@Service注解

SaBREzuIJVcvFpP

  • 测试
@Test
public void test2() {
    ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
    String[] names = context.getBeanDefinitionNames();
    for (String name : names) {
        System.out.println(name);
    }
}

HfCQVFSDP7lgmbB

指定包扫描规则

1. 指定排除规则
// excludeFilters Filter[] 扫描的时候按照指定的规则排除指定的组件
// 排除加了 @Controller 和 @Service 注解的组件
@ComponentScan(value = "cn.lwjppz", excludeFilters = {@Filter(type = FilterType.ANNOTATION, classes = {Controller.class, Service.class})})

效果:

2koKjwPXUAhe4qN

很明显和之前相比少了 userControlleruserService

2. 指定包含规则
// includeFilters Filter[] 扫描的时候只需要包含哪些组件
// 只扫描加了 @Controller 组件的组件
@ComponentScan(value = "cn.lwjppz", includeFilters = {@Filter(type = FilterType.ANNOTATION, classes = Controller.class)}, useDefaultFilters = false)

注意:使用 includeFilters 时要排除 Spring 默认的 Filters,需在 @ComponentScan 中加入 useDefaultFilters = false

效果:

atcug3hLy4AYBZp

现在就只有加了 @Controller 的组件被包含进来了

3. 也可使用 @ComponentScans 来指定多个扫描规则
@ComponentScans({
        @ComponentScan(value = "cn.lwjppz", includeFilters = {@Filter(type = FilterType.ANNOTATION, classes = Controller.class)}, useDefaultFilters = false)
})

效果是和之前的一样的。

4. 自定义规则
/**
 *  FilterType.ANNOTATION           按照注解
 *  FilterType.ASSIGNABLE_TYPE      按照给定的类型
 *  FilterType.ASPECTJ              使用 ASPECTJ 表达式
 *  FilterType.REGEX                使用正则表达式
 *  FilterType.CUSTOM               使用自定义规则
 */

8XJRmwf2v7KWIgC

注意:自定义 Filter 需实现 TypeFilter 接口

@Scope - 设置组件作用域

@Configuration
public class MainConfig2 {

    /**
     * 默认是单实例的
     * @see ConfigurableBeanFactory#SCOPE_PROTOTYPE  singleton
     * @see ConfigurableBeanFactory#SCOPE_SINGLETON  prototype
     * @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST request
     * @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION session
     * @return
     *
     * singleton    单实例(默认值)    IOC容器启动后会去调用方法创建对象,放入容器中
     *              以后每次获取都是从容器中拿(map.get())
     * prototype    多实例             IOC容器启动后并不会去调用方法创建对象放入容器中
     *              每次获取的时候才会调用方法创建对象,所以每次获取的对象都不相同
     * request      同一次请求创建一个实例
     * session      同一次 session 创建一个实例
     */
    @Scope("singleton")
    @Bean
    public User user() {
        return new User(1, "lisi", 20);
    }
}

测试:

@Test
public void test3() {
    ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig2.class);
    User bean1 = context.getBean(User.class);
    User bean2 = context.getBean(User.class);
    System.out.println(bean1 == bean2);
}

gPvzRnT1qFH87UJ

换成 prototype 之后

1RUx534fcPwpGSk

@Lazy - Bean懒加载

单实例bean,默认在容器启动的时候创建对象。 懒加载,容器启动时不创建对象,在第一次使用(获取)bean的时候创建,并初始化。