@Lazy注解--懒加载分析及FactoryBean接口
示例
代码
@Configuration
@Import(value = {CompentC.class,TulingImportSelect.class,TulingImportBeanfinitionRegister.class})
@ComponentScan(basePackages = {"com.tuling.parsebeandefinition"})
public class MainConfig {
@Bean
@Lazy
public CompentD compentD() {
return new CompentD();
}
}
当我们的实体类加上懒加载注解后,不会自动装配到IOC容器里。也就是1级缓存池中不会有
原因
finishBeanFactoryInitialization(beanFactory)
//冻结所有的 bean 定义 , 说明注册的 bean 定义将不被修改或任何进一步的处理
beanFactory.freezeConfiguration();
//实例化剩余的单实例bean
beanFactory.preInstantiateSingletons();
重点来了,面试官最爱在这问的
所以我们知道了懒加载的bean只有当被getBean调用的时候才会放入IOC容器的一级缓存池中。
FactoryBean
FactoryBean是个接口,实现这个接口必须实现他的方法,最重要的就是getObject
我们可以把实现这个接口,理解为偷梁换柱
public class MainClass {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx =
new AnnotationConfigApplicationContext(MainConfig.class);
CompentD compentD =(CompentD) ctx.getBean("compentA");
System.out.println(compentD);
}
}
@Component
public class CompentA implements FactoryBean {
public CompentA() {
System.out.println("compentA.....的构造方法");
}
@Override
public Object getObject() throws Exception {
return new CompentD();
}
@Override
public Class<?> getObjectType() {
return null;
}
}
来看doGetBean方法的getObjectForBeanInstance
name 以 & 开头,但 beanInstance 却不是 FactoryBean,则认为有问题。
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
}
如果上面的判断通过了,表明 beanInstance 可能是一个普通的 bean,也可能是一个FactoryBean。
如果是一个普通的 bean,这里直接返回 beanInstance 即可。
如果是FactoryBean,则要调用工厂方法生成一个 bean 实例。
//在这里会调用getObject()
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
factory.getObject();
最后来到我们实体类的
总结
最后会在getBean的时候,经过一系列的判断,
把实体类转为一个FactoryBean的泛型
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
实现了FactoryBean接口的类,会调用getObject方法返回最终的对象。
思考
怎么样把实现了FactoryBean接口的类,通过getBean之后,不会走getObject方法
AnnotationConfigApplicationContext ctx =
new AnnotationConfigApplicationContext(MainConfig.class);
CompentA compentA =(CompentA) ctx.getBean("&compentA");
System.out.println(compentA);
最后可以猜猜这段代码运行结果
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MainConfig.class);
CompentA compentA =(CompentA) ctx.getBean("&compentA");
System.out.println(compentA);
CompentD compentd =(CompentD) ctx.getBean("compentA");
System.out.println(compentd);
}
@Component
public class CompentA implements FactoryBean {
public CompentA() {
System.out.println("compentA.....的构造方法");
}
@Override
public Object getObject() throws Exception {
return new CompentD();
}
@Override
public Class<?> getObjectType() {
return null;
}
}