【Java面试】第十一天
🌟个人主页:时间会证明一切.
目录
- Springboot是如何实现自动配置的?
- Spring的@Autowired能用在Map上吗?
- List
- Map
- Set
- 数组
- 注意事项
- Spring的AOP在什么场景下会失效?
Springboot是如何实现自动配置的?
Spring Boot会根据类路径中的jar包、类,为jar包里的类自动配置,这样可以极大的减少配置的数量。简单点说就是它会根据定义在classpath下的类,自动的给你生成一些Bean,并加载到Spring的Context中。
SpringBoot通过Spring 的条件配置决定哪些bean可以被配置,将这些条件定义成具体的Configuration,然后将这些Configuration配置到spring.factories文件中(这种方式Springboot 2.7.0版本已不建议使用,最新的方式是使用 /META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports )
作为key: org.springframework.boot.autoconfigure.EnableAutoConfiguration的值
这时候,容器在启动的时候,由于使用了EnableAutoConfiguration注解,该注解Import的EnableAutoConfigurationImportSelector会去扫描classpath下的所有spring.factories文件,然后进行bean的自动化配置:
Spring的@Autowired能用在Map上吗?
可以的。
在Spring框架中,@Autowired 注解不仅可以用于单个bean的注入,还可以用于注入复杂的集合类型,如List、Map、Set等。这种机制非常有用,尤其是当你需要注入同一类型的多个bean时。
List
当你使用@Autowired在一个List字段上时,Spring会将所有匹配的bean类型注入到这个列表中。这是自动按类型注入的一个例子。这意味着如果你有多个bean都是同一接口的实现,Spring会将它们全部收集起来,注入到这个List中。
@Autowired
private List<HollisService> services; // 将注入所有HollisService类型的bean
Map
使用Map时,key通常是bean的名称,value是bean的实例。这允许你不仅按类型注入,还可以按名称引用具体的bean。这在你需要根据名称动态选择bean时非常有用。
@Autowired
private Map<String, HollisService> servicesMap; // 键是bean的名称,值是HollisService类型的实例
这通常用在工厂模式中,如:
Set
与List类似,使用Set可以注入所有匹配的bean类型,但注入到Set中的bean实例将是唯一的(无重复元素),这依赖于bean的equals和hashCode实现。
@Autowired
private Set<HollisService> servicesSet; // 将注入所有HollisService类型的bean,但每个实例只出现一次
数组
你也可以使用数组类型来注入。这与使用List类似,Spring会注入所有匹配类型的bean到数组中。
@Autowired
private HollisService[] servicesArray; // 将注入所有HollisService类型的bean
注意事项
当使用这些集合类型注入时,如果没有找到任何匹配的bean,Spring默认的行为是抛出异常。你可以通过设置@Autowired(required = false)来避免这种情况,这样如果没有找到匹配的bean,Spring就不会注入任何值(字段将保持为null)。
Spring的AOP在什么场景下会失效?
首先,Spring的AOP其实是通过动态代理实现的,所以,想要让AOP生效,前提必须是动态代理生效,并且可以调用到代理对象的方法。
什么情况下会不走代理对象的调用呢?
首先就是类内部的调用,比如一些私有方法调用,内部类调用,以及同一个类中方法的自调用等。如:
//1
public class MyService {
public void doSomething() {
doInternal(); // 自调用方法
}
public void doInternal() {
System.out.println("Doing internal work...");
}
}
//2
public class MyService {
public void doSomething() {
doInternal(); // 自调用私有方法
}
private void doInternal() {
System.out.println("Doing internal work...");
}
}
//3
public class OuterClass {
private class InnerClass {
public void doSomething() {
System.out.println("Doing something in inner class...");
}
}
public void invokeInnerClassMethod() {
InnerClass innerClass = new InnerClass();
innerClass.doSomething(); // 调用内部类方法
}
}
以上,都是因为在对象内部直接调用其他方法,就会用原始对象直接调用了,不会调用到代理对象,所以代理会失效。
类似的还有一种情况,虽然不是对象的自调用,但是他也是因为没有调用到代理对象,那就是调用static方法,因为这类方法是属于这个类的,并不是对象的,所以无法被AOP。
public class MyService {
public staic void doSomething() {
// static 方法
}
}
还有一种方法,也无法被代理,那就是final方法,由于AOP是通过创建代理对象来实现的,而无法对final方法进行子类化和覆盖,所以无法拦截这些方法。
public class MyService {
public final void doSomethingFinal() {
System.out.println("Doing something final...");
}
}
所以,那么总结一下就是以下几种情况,会导致代理失效,AOP不起作用:
1、私有方法调用
2、静态方法调用
3、final方法调用
4、类内部自调用
5、内部类方法调用