正文
01 @Lookup的作用
在平时写代码的过程中,经常会出现多例的模式。例如,可以指定Spring配置文件@Scope("prototype")的多例模式,如下。
@Component @Scope("prototype") public class PrototypeBean { ... }
但是假若如果在一个单例对象中使用这个实例,就会出现不是想要的结果如下:
@Component @Scope("singleton") public class SingletonBean { @Resource private PrototypeBean prototypeBean; public PrototypeBean getPrototypeBean() { return prototypeBean; } }
从SingletonBean对象中每次获取PrototypeBean对象,发现都是一个确定的值,如下测试:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath*:beans.xml"}) public class SpringTest { @Resource private SingletonBean singletonBean; @Test public void test01() { System.out.println(singletonBean.getPrototypeBean()); System.out.println(singletonBean.getPrototypeBean()); System.out.println(singletonBean.getPrototypeBean()); } }
测试结果如下,可以得到PrototypeBean对象每一次都是相同的,那我们如何可以获取不同的呢?实际上,这个注解就是简化每一位程序员的操作,可以顺利地达到每一次都是不同对象的目的。
... vip.breakpoint.bean.PrototypeBean@3c419631 vip.breakpoint.bean.PrototypeBean@3c419631 vip.breakpoint.bean.PrototypeBean@3c419631
02 采用ApplicationContextAware实现
修改SingletonBean对象代码如下:
@Component @Scope("singleton") public class SingletonBean implements ApplicationContextAware { private ApplicationContext applicationContext; public PrototypeBean getPrototypeBean() { return this.applicationContext.getBean(PrototypeBean.class); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } }
测试代码保持不变,测试结果如下:
七月 14, 2022 9:29:17 下午 org.springframework.test.context.support.AbstractTestContextBootstrapper getDefaultTestExecutionListenerClassNames 信息: Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener, org.springframework.test.context.event.EventPublishingTestExecutionListener] 七月 14, 2022 9:29:17 下午 org.springframework.test.context.support.AbstractTestContextBootstrapper getTestExecutionListeners 信息: Using TestExecutionListeners: [org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@224edc67, org.springframework.test.context.support.DependencyInjectionTestExecutionListener@14acaea5, org.springframework.test.context.support.DirtiesContextTestExecutionListener@46d56d67, org.springframework.test.context.event.EventPublishingTestExecutionListener@d8355a8] vip.breakpoint.bean.PrototypeBean@3e92efc3 vip.breakpoint.bean.PrototypeBean@1622f1b vip.breakpoint.bean.PrototypeBean@72a7c7e0 Process finished with exit code 0
可以看出,使用ApplicationContextAware方式成功了,并且每一次获取的PrototypeBean对象都是不同的。
03 使用@Lookup注解实现
修改后SingletonBean对象的代码如下:
@Component @Scope("singleton") public class SingletonBean { @Lookup public PrototypeBean getPrototypeBean() { return null; } }
测试代码不变,一起看一下结果吧!
七月 14, 2022 9:30:58 下午 org.springframework.test.context.support.AbstractTestContextBootstrapper getDefaultTestExecutionListenerClassNames 信息: Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener, org.springframework.test.context.event.EventPublishingTestExecutionListener] 七月 14, 2022 9:30:58 下午 org.springframework.test.context.support.AbstractTestContextBootstrapper getTestExecutionListeners 信息: Using TestExecutionListeners: [org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@475530b9, org.springframework.test.context.support.DependencyInjectionTestExecutionListener@1d057a39, org.springframework.test.context.support.DirtiesContextTestExecutionListener@26be92ad, org.springframework.test.context.event.EventPublishingTestExecutionListener@4c70fda8] vip.breakpoint.bean.PrototypeBean@7b2bbc3 vip.breakpoint.bean.PrototypeBean@a1153bc vip.breakpoint.bean.PrototypeBean@1aafa419 Process finished with exit code 0
可以从测试的结果看出,采用@Lookup注解实现了获取不同的对象,达到了最开始的目的。
03 后记
@Lookup注解简化了程序员的操作,它的主要的实现的原理是,当遇到这个注解的时候,会从上下文中根据方法的返回类型进行获取注册在IOC容器中的实例对象,也就是调用getbean的方法。