1.对于新手来说,最明显的不过是在applicationContext.xml文件上没有加<context:component-scan base-package="com.xxx"/>,或者明明写了,但Spring还是没有将该类注入到容器中.其实,很多人都喜欢将包的路径写的非常的详细,比如:com.xxx.xxx.service等,这样做的好处是Spring启动的时候,扫描的类更少了,效率更高了.这样做其实无可厚非,但是有些时候,你难免会把所有需要交给Spring管理都放在这个包下,这就导致有些放在其它包下的,贴有@Controller,@Service,@Repository,@Component等注解的类也不会交给Spring管理了.所以,最稳妥的方法就是,扫描所有的包,如下
对于使用idea的同学来说,想要知道有没有扫描到你想要的类,可以直接点击这个配置旁边类似叶子的图标,那里可以看到当前所有被Spring所管理的类.
2.主要说一下本人最近遇到的一个比较常识性但又容易踩坑的地方,我们都知道,如果你想要通过@Autowired注入一个对象,那么前提是当前你所在的这个类本身需要被Spring管理, 举个例子: 你想要在一个Controller里注入一个Service,那么不仅这个Service要贴上@Service,这个Controller也要贴上@Controller, 如果当前的Controller并未贴上@Controller,那就无法注入,因为Spring并未管理当前Controller的生命周期.
重点来了,如果我的一个Service A明明已经贴上了注解,另一个Service B也贴上了注解,而且都被扫描到了,那为什么还是无法通过@Autowired注入呢?
原理其实很简单, 在SMSImpl里要调用receiptService的方法,首先SMSImpl这个类就要从容器中拿,而不能直接new出来,因为交给Spring管理的类一般默认是单例的,它会为这个对象注入属性,但自己new出来的类,就不会注入这个属性了,而我拿到的SMSImpl实现类其实就是我自己new出来的.
如图,在某个类中,启动容器先加载静态代码块的时候,把所有实现了IMessageSMS接口的类都放入在一个Map中,而这些类其实都是newInstance出来的,所以这些类本身是没有属性的对象的,所以在调用的时候,就为null了,而解决的办法也很简单,直接去容器中拿出receiptService对象即可.