ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Spring中的lookup-method的作用

2022-01-03 01:34:43  阅读:213  来源: 互联网

标签:ObjectA ObjectB ObjectC LOG Spring class public lookup method


在Spring中,默认创建的对象是单例的,Spring会在一级缓存中持有该对象,方便下次直接获取,如果创建的是多例对象,Spring每次则会创建新的对象,不会进行缓存;

如果想在一个单例bean下引用一个多例bean,此时需要使用LookUp来解决;

 

测试如下:

ObjectA的getObjectC方法用@Lookup注解修饰或在xml配置<lookup-method>属性,而ObjectB和ObjectC对象都是通过@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)配置成了多例;

@Component
public class ObjectA {
	private final static Log LOG = LogFactory.getLog(ObjectA.class);

	@Autowired
	private ObjectB objectB;

	@Autowired
	private ObjectC objectC;

	public ObjectA() {
		LOG.info("ObjectA constructor");
	}

	public ObjectB getObjectB() {
		return objectB;
	}

	@Lookup
	public ObjectC getObjectC() {
		return objectC;
	}
}

  

@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Component
public class ObjectB {
	private final static Log LOG = LogFactory.getLog(ObjectB.class);

	public ObjectB() {
		LOG.info("ObjectB constructor");
	}
}

  

@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Component
public class ObjectC {
	private final static Log LOG = LogFactory.getLog(ObjectC.class);

	public ObjectC() {
		LOG.info("ObjectC constructor");
	}
}

  

@Test
public void lookUpMethodTest() {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    context.register(MethodOverrideConfig.class);
    context.refresh();
    ObjectA objectA = context.getBean(ObjectA.class);

    ObjectB objectB1 = objectA.getObjectB();
    ObjectB objectB2 = objectA.getObjectB();

    System.out.println(objectB1);
    System.out.println(objectB2);

    ObjectC objectC1 = objectA.getObjectC();
    ObjectC objectC2 = objectA.getObjectC();
    System.out.println(objectC1);
    System.out.println(objectC2);
}

  

结果如下:

ObjectB和ObjectC虽然是配置成多例,但是通过getBean多次获取ObjectB和ObjectC对象的效果不同,每次获取ObjectB的效果还是跟单例一样,而每次获取ObjectC的效果才是多例的;

 

分析如下:

AbstractAutowireCapableBeanFactory#createBeanInstance方法是使用合适的实例化策略来创建新的实例,创建的过程是会调用instantiateBean方法;

 

AbstractAutowireCapableBeanFactory#instantiateBean

 

instantiateBean方法是使用无参构造器进行实例化对象;通过getInstantiationStrategy方法获取实例化策略,根据获取的策略处理instantiate方法实例化对象的操作;

 

bean的生成策略,默认是cglib,而CglibSubclassingInstantiationStrategy是继承SimpleInstantiationStrategy,如下图;

 

bean实例化策略为CglibSubclassingInstantiationStrategy时,调用instantiate方法是SimpleInstantiationStrategy的;

SimpleInstantiationStrategy#instantiate(org.springframework.beans.factory.support.RootBeanDefinition, java.lang.String, org.springframework.beans.factory.BeanFactory)

 

上面的测试代码中ObjectA#getObjectC有@Lookup注解修饰,因此对应的methodOverrides不为空,执行instantiateWithMethodInjection方法的逻辑,如下图;

 

CglibSubclassingInstantiationStrategy.CglibSubclassCreator#instantiate

对于有设置了methodOverride属性的bean会设置对应的方法拦截器;

 

当调用有@Lookup注解修饰或xml配置<lookup-method>的方法时,调用对应的方法会先进入拦截器CglibSubclassingInstantiationStrategy.LookupOverrideMethodInterceptor#intercept;

首先通过beanDefinition获取到对应的LookupOverride的属性,通过属性获取到对应方法的返回值,调用getBean实例化对象;

 

参考:

https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-factory-method-injection

标签:ObjectA,ObjectB,ObjectC,LOG,Spring,class,public,lookup,method
来源: https://www.cnblogs.com/coder-zyc/p/15758841.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有