在一次采访中,面试官问我“如何知道在哪里搜索组件或Beans?”。
由于我不知道内部流程的细节,所以我无法正确回答这个问题。
我说通过@Component和@Bean我们可以找到。但是面试官对这个问题并不满意。如果有人知道,请分享你的知识。提亚
发布于 2020-06-04 03:57:21
我喜欢回答面试问题。看下面..。
@ComponentScan如果您了解组件扫描,则了解Spring。
Spring是一个依赖注入框架。这一切都是关于bean和依赖关系中的连接。
定义Spring的第一步是添加正确的注释- @Component、@Service或@Repository。
但是,Spring不知道bean的情况,除非它知道在哪里搜索它。
这部分“告诉春天在哪里搜索”被称为组件扫描.
定义必须扫描的包。
一旦为包定义了组件扫描,Spring就会搜索包及其所有子包中的组件/bean。
定义组件扫描
。
方法1: Spring项目中的组件扫描
如果您的其他包层次结构在主应用程序下面,并带有@SpringBootApplication注释,那么您将被隐式组件扫描所覆盖。如果其他包中有bean/组件不是主包的子包,则应手动将它们添加为@ComponentScan。
考虑下课
package com.in28minutes.springboot.basics.springbootin10steps;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class SpringbootIn10StepsApplication {
public static void main(String[] args) {
ApplicationContext applicationContext =
SpringApplication.run(SpringbootIn10StepsApplication.class, args);
for (String name: applicationContext.getBeanDefinitionNames()) {
System.out.println(name);
}
}
}@SpringBootApplication是在包com.in28minutes.springboot.basics.springbootin10steps中的SpringbootIn10StepsApplication类中定义的
@SpringBootApplication定义了包com.in28minutes.springboot.basics.springbootin10steps上的自动组件扫描。
如果您的所有组件都定义在上面的包或它的子包中,那么您就没事了。
但是,假设其中一个组件是在包com.in28minutes.springboot.somethingelse中定义的
在这种情况下,需要将新包添加到组件扫描中。
你有两个选择:
选项1:
@ComponentScan(“com.in28minutes.springboot”)
@SpringBootApplication
public class SpringbootIn10StepsApplication {...}选项2::定义为数组
@ComponentScan({"com.in28minutes.springboot.basics.springbootin10steps","com.in28minutes.springboot.somethingelse"})
@SpringBootApplication
public class SpringbootIn10StepsApplication {...}方法2:非Spring启动项目
选项1:
@ComponentScan(“com.in28minutes)
@Configuration
public class SpringConfiguration {...}备选方案2:
@ComponentScan({"com.in28minutes.package1","com.in28minutes.package2"})
@Configuration
public class SpringConfiguration {...}XML应用程序上下文:
<context:component-scan base-package="com.in28minutes" />特定于的多个包:
<context:component-scan base-package="com.in28minutes.package1, com.in28minutes.package2" />发布于 2020-06-04 04:29:16
IoC (反转控制)容器,用类ApplicationContext表示在Spring中,是这一切背后的大脑。这一切归结为以一种非常强大的方式使用反射。
为了简化,让我们考虑以下步骤(所有步骤都是通过反射完成的):
@Component
@Component,创建该类的新实例@Autowired注释的所有字段,并为每个字段创建一个实例。<代码>H 113将所有内容保存在上下文中,以便以后使用。H 214G 215
这个答案的其余部分是一个oversimplified版本,它描述了这一切是如何发生的,就像我们自己做的那样。谢天谢地,春天是存在的,我们不需要自己去做。
注释
@Retention(RetentionPolicy.RUNTIME)
public @interface Node {}
@Retention(RetentionPolicy.RUNTIME)
public @interface Wire { }一些用于测试的带注释类
@Node
public class ServiceA {
@Wire
private ServiceB serviceB;
public void doAStuff() {
System.out.println("A stuff");
serviceB.doBStuff();
}
}
@Node
public class ServiceB {
public void doBStuff() {
System.out.println("B stuff");
}
}IoC容器
import org.reflections.Reflections;
/* dependency org.reflections:reflections:0.9.12 */
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class IoC {
private final Map<Class<?>, Object> allNodes = new HashMap<>();
public void start() {
Reflections reflections = new Reflections(IoC.class.getPackageName());
Set<Class<?>> nodeClasses = reflections.getTypesAnnotatedWith(Node.class);
try {
for (Class<?> c : nodeClasses) {
Object thisInstance = c.getDeclaredConstructor().newInstance();
for (Field f : c.getDeclaredFields()) {
f.setAccessible(true);
if (f.getDeclaredAnnotation(Wire.class) != null) {
Object o = f.getType().getDeclaredConstructor().newInstance();
f.set(thisInstance, f.getType().cast(o));
}
}
allNodes.put(c, thisInstance);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public <T> T getNodeByType(Class<T> cls) {
return cls.cast(allNodes.get(cls));
}
}主要的课程开始了。
public class Application {
public static void main(String[] args) {
IoC ioc = new IoC();
ioc.start();
ServiceA serviceA = ioc.getNodeByType(ServiceA.class);
serviceA.doAStuff();
}
}这将产生以下结果:
A stuff
B stuff当然,Spring比这个更强大(更健壮)。它允许使用@ComponentScan、具有不同名称的相同类型的bean、单例/原型作用域bean、构造函数连接、属性文件注入等多种方式进行自定义包扫描。当涉及Spring时,@SpringBootApplication注释确保它找到并连接所有@Controller注释类,并设置一个Netty/Jetty/Tomcat嵌入式服务器来侦听请求,并根据带注释的类型重定向到适当的控制器。
发布于 2020-06-04 03:07:43
在哪里搜索bean是由@ComponentScan定义的,它可以在用于引导Spring的@Configuration类上进行注释。
例如,它有一个名为scanBasePackages的属性,它告诉Spring扫描bean(一个类被注释为@Component或它的类固醇类型,如@Service、@Repository、@Controller等)。只从某些包和它的子包。
然后,对于已注册的每个bean,继续查看是否有@Bean.If是的任何方法注释,也可以将它们注册为bean。
https://stackoverflow.com/questions/62186071
复制相似问题