使用spring,则所有bean统一交给spring管理,spring负责初始化、销毁等整个声明周期。所有bean的定义通过配置文件或javaConfig方式。启动时统一初始化并加载至spring的applicationContext中,通过其getBean方法获取。
但有时为了加快系统启动速度,并不需启动时立刻初始化并加载,可以在使用其时才初始化并加载。本文通过示例进行说明。
使用gradle和idea,这里直接给出build.gradle文件内容。使用maven自己对照修改下。
使用spring及test相关依赖。
build.gradle
group 'com.dataz'
version '1.0-SNAPSHOT'
apply plugin: 'idea'
apply plugin: 'java'
sourceCompatibility = 1.8
repositories {
mavenCentral()
maven { url 'http://maven.springframework.org/release' }
maven { url 'http://download.java.net/maven/2' }
maven { url 'https://plugins.gradle.org/m2/' }
}
dependencies {
// 日志依赖
compile group: 'ch.qos.logback', name: 'logback-classic', version: '1.7.21'
compile group: 'org.springframework', name: 'spring-beans', version: '5.0.1.RELEASE'
compile group: 'org.springframework', name: 'spring-context', version: '5.0.1.RELEASE'
testCompile group: 'org.springframework', name: 'spring-test', version: '5.0.1.RELEASE'
testCompile group: 'junit', name: 'junit', version: '4.12'
}
ConfigBean有init方法和destory方法。还有布尔型isInitialized public静态属性。如果初始化完成其值为true。
ConfigBean.java
package com.dataz.entity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ConfigBean {
private Logger logger = LoggerFactory.getLogger(ConfigBean.class);
private String value;
public static boolean isInitialized;
public ConfigBean(){
isInitialized = true;
}
public ConfigBean(String value){
this();
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public void destroy() {
logger.info("destroy called for ConfigBean({})",value);
}
public void init() {
logger.info("init called for ConfigBean({})",value);
}
public String toString() {
return String.format("ConfigBean: value[ %s ]",value);
}
}
这里使用javaConfig方式配置。通过@Configuration注解,spring会自动识别并加载,与xml配置功能一致。
SysConfig.java
@lazy注解让该ConfigBean延迟加载,同时指定其初始化和销毁方法。
SysConfig.java
package com.dataz;
import com.dataz.entity.ConfigBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
@Configuration
public class SysConfig {
@Bean(initMethod = "init",destroyMethod = "destroy")
@Lazy
public ConfigBean configBean(){
return new ConfigBean("A");
}
}
context.getBean()调用之前,可以看到configBean没有初始化,调用之后初始化成功。读者可以尝试注释@Lazy,对比查看结果。
ConfigBeanTest.java
package com.dataz.entity;
import com.dataz.SysConfig;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=SysConfig.class)
public class ConfigBeanTest {
private Logger logger = LoggerFactory.getLogger(ConfigBeanTest.class);
@Autowired
private ApplicationContext context;
private ConfigBean configBean;
@Test
public void lazyTest(){
logger.info("configBean init flag:{}",ConfigBean.isInitialized);
ConfigBean.isInitialized = false;
logger.info("bean lazy load...............");
logger.info("configBean :{}",context.getBean("configBean"));
logger.info("configBean init flag:{}",ConfigBean.isInitialized);
}
}
输出结果:
com.dataz.entity.ConfigBeanTest - configBean init flag:false
com.dataz.entity.ConfigBeanTest - bean lazy load...............
com.dataz.entity.ConfigBean - init called for ConfigBean(A)
com.dataz.entity.ConfigBeanTest - configBean :ConfigBean: value[ A ]
com.dataz.entity.ConfigBeanTest - configBean init flag:true
o.s.c.s.GenericApplicationContext - Closing
com.dataz.entity.ConfigBean - destroy called for ConfigBean(A)
本文通过javaConfig方式测试spring懒加载。xml配置方式通过default-lazy-init
和 lazy-init
属性,前者统一指定,后者在bean定义时指定,与@lazy对应。那么通过注解方式可以统一指定默认懒加载吗?当然也可以,@lazy可以直接用在@bean或@Component定义的类上,也可以使用在 @Configuration定义类上,后者表示该类中所有@Bean方法对应类被懒加载,与default-lazy-init
功能一致。