Spring IOC 注解 — @Bean,@Scope 和 @Lazy

Spring可以做很多事情,为企业级开发提供了丰富的功能,但是这些功能都依赖于它的两个核心特性:依赖注入(DI)或控制反转(IOC)和面向切面编程(AOP)。如果说Spring IOC容器将开发人员从对Bean(实例)的管理的繁重任务中脱离出来,那么Spring提供的注解则将开发人员从Spring中繁复的xml配置中解脱出来。

Spring为我们提供了很多注解,用于将我们自己写的组件交给Spring IOC容器管理,比如:我们可以使用@Controller注解标注该类为一个控制器,使用@Service标注一个类为业务逻辑类,@Repository标注一个类为数据库访问类,@Component标注一个类为组件,@Configuration标注该类是一个配置类。但是对于第三方框架或者jar包,这些组件就无能为力了,不过Spring为我们准备了其他注解,将第三方无法使用上述注解的类交给Spring管理,比如:@Bean,@Import等

@Bean注解的使用

1.@Bean注解用于@Configration注解的类的方法上,用于创建一个Spring IOC管理的Bean,默认情况下,被创建的bean在Spring中的名称为方法名,如下代码所示,创建的bean的名称为printComponent:

@Bean
public PrintComponent printComponent() {
    return new PrintComponent();
}

2.Spring为@Bean注解提供了 value和name属性,它们的类型为字符串数组,我们可以使用这两个属性为该bean指定名称,但是这两个直接不能同时使用,只能使用其中的一个。 如果指定了多个名称,在使用getBeanDefinitionNames方法打印Bean名称时,只打印第一个名称。代码示例如下:

@Bean(name="print")
public PrintComponent printComponent() {
    return new PrintComponent();
}
//一个bean实例两个名称,使用context.getBean("printComponent")和context.getBean("print")获取的是一个实例
@Bean(name={"print","printComponent"})
public PrintComponent printComponent() {
    return new PrintComponent();
}
//一个bean实例两个名称,使用context.getBean("printComponent")和context.getBean("print")获取的是一个实例
@Bean(value={"print1","printComponent2"})
public PrintComponent printComponent() {
    return new PrintComponent();
}

将Bean交给Spring IOC之后,由IOC负责对Bean的实例化,可能我们需要在Bean实例化之后(构造方法调用之后)和容器关闭之前做一些操作。此时,我们可以使用@Bean注解的initMethod方法为该实例指定一个初始化方法,使用destroyMethod为该实例指定一个销毁方法。如下代码,initMethod方法会在实例化之后调用,destoryMethod方法会在IOC容器销毁时被调用

public class PrintComponent {
	
    public PrintComponent() {
	System.out.println("构造方法");
    }
	
    public void initMethod() {
        System.out.println("打印之前,检查是否准备好石墨和纸张");
    }

    public void printContent() {
        System.out.println("打印中");
    }

    public void destoryMethod() {
        System.out.println("报警:已经打印完成,可以取出打印的纸张");
    }
}
@Bean(value="print",initMethod ="initMethod", destroyMethod="destoryMethod")
public PrintComponent printComponent() {
    return new PrintComponent();
}

@Scope注解

默认情况下交给Spring管理的Bean都是单例的,如果我们想使用多例模式的Bean,则可以使用@Scope注解。@Scope注解用于为Bean指定作用域。Spring中的Bean有四种作用域:默认为singleton:单实例的(默认值):ioc容器启动会调用方法创建对象放到ioc容器中。以后每次获取就是直接从容器(map.get())中拿,prototype:多实例的:ioc容器启动并不会去调用方法创建对象放在容器中。每次获取的时候才会调用方法创建对象;request:同一次请求创建一个实例,session:同一个session创建一个实例。值得注意的是如果@Bean中包含initMethd属性和destroyMethod属性,多例的Bean只会指定initMethod方法中指定的方法,destroyMethod中指定的方法不会执行。

@Scope("prototype")
@Bean(value="print")
public PrintComponent printComponent() {
    return new PrintComponent();
}

@Lazy注解

默认情况下Spring在容器启动的时候创建对象;如果我们不想让容器启动的时候就创建对象,而是在获取实例的时候才创建对象,则可以使用@Lazy注解:

@Lazy
@Bean(value="print", initMethod = "initMethod",destroyMethod="destoryMethod")
public PrintComponent printComponent() {
    return new PrintComponent();
}

@PostConstruct与@PreDestroy

前面我们提到我们可以使用@Bean注解的initMethod方法为该实例指定一个初始化方法,使用destroyMethod为该实例指定一个销毁方法。这两个方法分别在实例创建之后和容器销毁之前被调用,除此之外,我们还可以在Bean的方法上标注@PostConstruct和@PreDestroy注解。他们是JSR250提供的两个注解,@PostConstruct在实例创建之后被调用,@PreDestroy在容器被销毁之前调用。代码如下:

public class PrintComponent {
    public PrintComponent() {
        System.out.println("构造方法");
    }
    @PostConstruct
    public void initMethod() {
        System.out.println("打印之前,检查是否准备好石墨和纸张");
    }
    public void printContent() {
        System.out.println("打印中");
    }
    @PreDestroy
    public void destoryMethod() {
        System.out.println("报警:已经打印完成,可以取出打印的纸张");
    }
}
@Bean(value="print")
public PrintComponent printComponent() {
    return new PrintComponent();
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章