我们习惯这样编写代码:
在service层写接口,然后用实现类去实现接口,并且将实现类注入到容器中
@Service
public class AccountServiceImpl implements AccountService {}
在controller层却是用接口操作service的bean的方法,
@Autowired
private AccountService userService;
为神魔这样?
理解:
1)注入的就是实现类,只不过拿接口来接收,接受的类型为接口,面向接口编程,那么为何要面向接口编程?这就涉及到使用接口做代理,因为通过@autowired的对象是通过接口的方式会使用jdk动态代理,jdk动态代理只能对实现接口的类生成代理,而不能针对类。
2)注入的是实现类对象,接收的是接口;理解为多态;
如果一个service接口有多个实现类呢?
controller类中使用@resource并通过byname的方式注入,不要用@autowired这种通过类型的方式了,
Service层(此时有两个接口实现类)
@Service("PCIImpt1")class PCIImpt1 imeplements PCI{}@Service("PCIimpt2")class PCIImpt2 imeplements PCI{}
Controller层
@Resource(name="PCIimpt2") //填PCIimpt1,注入PCIimpt1实现类,填PCIimpt2,则注入PCIimpt2实现类
private PCI pci; //注入接口以Resource手动指定接收
@Service注解是放实现类上的而非接口上
今天用springboot写多模块项目,写完第一个Controller类,注入的Service接口是ok的,然后写第二个Controller类就一直报错。这把我给搞懵逼了,为什么我第一个Controller没错,第二个错了,我代码都一样的啊。
我看他说没扫描到,就去看了下@Service注解,有啊。然后我再去看包名,也对的啊。多模块下面每个模块的包名都一样的,能够被@SpringBootApplication扫描到啊,彻底蒙圈了。
看来看去我都没找到哪里错了,好吧,1个半小时过去了,我自己找不到,去百度去问人。这是越来越蒙圈(百度要不是说包名要一样,要不就是说@SpirngBootApplication扫描同级及下层所有子包,我都知道啊,概念清楚,也没错,包名我又再对了一遍。然后再就是手动扫描,自己额外写注解,无论是@ComponentScan和@SpirngBootApplication(“xx”)我都试了,中间倒是掌握了个小知识——手动用注解扫描的话,记得还要手动把@SpringBootApplication注解所在的类的所在包一起扫进去)。
3个小时了,我彻底放弃了。准备重来一次,重新上git拉了个模板,把自己的代码文件一个一个拉过去,(以前出现过一次两个项目代码完全一样的,就是一个对了,一个出问题,现在怀疑是当时导入的maven依赖有冲突,一个运气好莫名其妙对了,一个运气差)拉着拉着我就 发现刚才好像有个文件没有@Service啊,额。再一看,好吧,还真没有,把@Service写到接口上去了,Impl实现类上没有@Service,额。无语,只能恨自己眼瞎,看包名看了一遍又一遍就是没看@Serivce到底放在什么位置。
总结一下:老老实实跟着IDEA的报错去找,这要是老老实实从service类开始开,细心一点,三个小时就不会浪费了。(也是自己技能没掌握扎实,我估计是当时犯浑,没搞清@Service放接口和放实现类上的差距)
过了1个多星期了,这几天复习了spring,spring可以管理部分工具类,但是不可以管理接口,也就是@Controller,@Component,@Repository,@Service不能放接口上。