之前在《如何把对象放入spring容器》这篇文章中,提到了registerSingleton()方法。说这个方法有些鸡肋。
利用这篇文章解释一下为什么说这个方法它比较鸡肋呢。
注:读这篇文章前需要你对spring的依赖关系有一定的了解,否则可能看起来吃力一些。
如果实在看不懂,就记住用法就行了,不用纠结。
一、关于存在的问题
/**
* 按照这种写法的话,
* 因为当前要托管给spring容器的对象是我新new出来的,名称为EvanService,
* 依赖EvanService的对象 名称为PersonService。EvanService依赖的对象 名称为TomService。
* 这就存在两个问题:
* 1.如果Spring管理的PersonService,依赖对象EvanService,在所有对象完成实例化后,你才将EvanService托管给spring容器,此时是没有作用的。
* 因为你需要在所有对象实例化之前,就将EvanService托管给spring。这样依赖EvanService的 PersonService对象才能完成实例化。
* 2.如果EvanService对象,依赖TomService对象。你需要做的是先把EvanService对象先托管给spring容器,然后从spring容器中获取EvanService对象。
* 但是因为此时这种写法,你是自己new的(此时并没有处理EvanService和TomService的依赖关系),然后才交给spring,这样也是没有任何意义的。
*/
二、问题1.代码证明
//你可以把EvanService当成是与第三方应用交互产生的对象。
public class EvanService {
}
@Component
public class PersonService {
@Autowired
EvanService evanService;
public void showEvanServiceResult() {
System.out.println(evanService);
}
}
错误示范:(注意这样是错误的) 对应问题1.
public class TestFirst {
public static void main(String[] args) {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
EvanService evanService = new EvanService();
ac.getBeanFactory().registerSingleton("evanService",evanService);
ac.getBean(PersonService.class).showEvanServiceResult();
}
}
正确写法:
/**
* 按照这种写法的话,
* 这样的写法我们就解决了部分问题,什么问题呢?解决了现有类依赖新对象的问题。
* 这样写的话,是先将我们的EvanService托管给spring容器,也就是注入到spring容器中,这样的话,然后再进行bean的实例化,
* 这样的PersonService此时依赖的EvanService就已经是被spring容器管理的bean了。所以能够正常打印。
*
* 但是这样写还是有问题,问题就是如果我们的新类,还需要依赖现有类怎么办?
* 通俗的讲就是如果EvanService需要依赖 TomService,在EvanService中@Autowired TomService。
* 因为此时的EvanService是new出来的(实际有可能是第三方交互产生),所以肯定没法处理与TomService的依赖关系。
* 所以还是没办法解决,这就是registerSingleton()这个方法鸡肋的地方。
* 请看 三、问题2.代码证明
*/
public class TestSecond {
public static void main(String[] args) {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
EvanService evanService = new EvanService();
ac.getBeanFactory().registerSingleton("evanService",evanService);
//将扫描到的类注册到spring容器
ac.register(AppConfig.class);
//刷新容器,完成bean的实例化
ac.refresh();
ac.getBean(PersonService.class).showEvanServiceResult();
}
}
运行结果:
com.evan.service.EvanService@7ae42ce3
三、问题2.代码证明
package com.evan.service;
public class TomService {
}
package com.evan.service;
import org.springframework.beans.factory.annotation.Autowired;
//你可以把EvanService当成是与第三方应用交互产生的对象。
public class EvanService {
@Autowired
TomService tomService;
public TomService showTomServiceResult() {
return tomService;
}
}
package com.evan.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class PersonService {
@Autowired
EvanService evanService;
public void showEvanServiceResult() {
System.out.println(evanService);
System.out.println(evanService.showTomServiceResult());
}
}
public class TestSecond {
public static void main(String[] args) {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
EvanService evanService = new EvanService();
ac.getBeanFactory().registerSingleton("evanService",evanService);
//将扫描到的类注册到spring容器
ac.register(AppConfig.class);
//刷新容器,完成bean的实例化
ac.refresh();
ac.getBean(PersonService.class).showEvanServiceResult();
}
}
运行结果:
//TomService打印结果为null,证明我们问题2.的存在。
com.evan.service.EvanService@7ae42ce3
null
四、结论
TomService打印结果为null,证明我们问题2.的存在。因为类似EvanService这种与第三方交互产生的对象或者new出来的对象,总是新产生的所以我们无法控制。所以说这个方法有些鸡肋。