@Service
public class BookServiceImpl implements BookService {
...
}
可以通过下面3种方式获取:
@Autowired
private BookService bookService;
@Autowired
private BookServiceImpl bookServiceImpl;
private BookService bookService;
@Autowired
public void injectDependency(BookService bookService) {
this.bookService = bookService;
}
private BookService bookService;
@Autowired
public MyClass(BookService bookService) {
this.bookService = bookService;
}
无论使用哪种方式,Spring Boot都会自动查找并注入实现了BookService接口的Bean,从而可以在代码中使用BookService接口的功能。需要注意的是,如果容器中存在多个实现了BookService接口的Bean,可以使用@Qualifier注解来指定具体要注入的Bean。例如:
@Autowired
@Qualifier("myBookService")
private BookService bookService;
也可以使用@Resource来制定注入的bean名字,例如:
@Resource(name = "myBookService")
private BookService bookService;
这样,可以根据myBookService的名称来注入对应的Bean。
当使用@Autowired或@Resource注解时,Spring会根据指定的名称或类型在ApplicationContext中查找对应的bean实例。底层实现中,Spring会调用ApplicationContext的getBean方法,传入指定的名称或类型作为参数。
验证代码:
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(Application.class, args);
System.out.println(applicationContext.getBean(BookService.class));
System.out.println(applicationContext.getBean(BookServiceImpl.class));
System.out.println(applicationContext.getBean("bookServiceImpl"));
System.out.println(applicationContext.getBean("bookService"));
}
cn.forlan.service.impl.BookServiceImpl@68ddd415
cn.forlan.service.impl.BookServiceImpl@68ddd415
cn.forlan.service.impl.BookServiceImpl@68ddd415
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'bookService' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:816)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1288)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1109)
at cn.forlan.Application.main(Application.java:36)
可以看到注册到Spring中的名称是bookServiceImpl,也就是名称是将类名的首字母小写
作为Bean的名称。类型是BookService.class和BookServiceImpl.class,也就是除了加@Service的类,也会把类实现的接口也注册进入。
在Spring Boot中,当使用@Autowired注解注入接口时,Spring会根据接口的类型查找对应的实现类。Spring使用了依赖注入和反射机制来实现这一功能。
当使用@Autowired注解时,Spring会扫描应用程序上下文中的所有bean,并尝试将其与接口类型进行匹配。如果找到多个匹配的实现类,Spring会抛出异常。如果找不到匹配的实现类,Spring也会抛出异常。
为了确保@Autowired注解能够正确地找到接口的实现类,您需要确保以下几点:
源码如下::
调用方法栈如下:
isTypeMatch:537, AbstractBeanFactory (org.springframework.beans.factory.support)
doGetBeanNamesForType:530, DefaultListableBeanFactory (org.springframework.beans.factory.support)
getBeanNamesForType:503, DefaultListableBeanFactory (org.springframework.beans.factory.support)
getBeanNamesForType:480, DefaultListableBeanFactory (org.springframework.beans.factory.support)
getBeanNamesForType:473, DefaultListableBeanFactory (org.springframework.beans.factory.support)
resolveNamedBean:1159, DefaultListableBeanFactory (org.springframework.beans.factory.support)
resolveBean:420, DefaultListableBeanFactory (org.springframework.beans.factory.support)
getBean:350, DefaultListableBeanFactory (org.springframework.beans.factory.support)
getBean:343, DefaultListableBeanFactory (org.springframework.beans.factory.support)
getBean:1127, AbstractApplicationContext (org.springframework.context.support)
总的来说,就是通过DefaultListableBeanFactory的getBeanNamesForType,最终调用doGetBeanNamesForType去匹配,返回和接口相关的类,比如它的子类,如果有多个,会报错,我们可以指定名称,进行过滤,最终返回一个bean。