History Of Dependency Lookup
Dependency lookup
:→ DI
→ 依赖查找
Spring的很多技术实际上是来源于JavaEE J2SE JNDI里的相关实现
- 单一类型依赖查找 Singleton Lookup
- JNDI:javax.naming.Context #lookup(javax.naming.Name)
- Java Beans:java.beans.beancontext.BeanContext
- 集合类型依赖查找 List Lookup
- Java Beans:java.beans.beancontext.BeanContext
- 层次性依赖查找 Hierarchical Lookup
- Java Beans:java.beans.beancontext.BeanContext
Spring对于依赖查找的实现会比
JNDI
和JavaEE
更加优雅简洁,这也是使用Spring的一个原因
Singleton Lookup
单一类型依赖查找接口:BeanFactory
- 根据Bean名称查找
public interface BeanFactory { /** * 最常用的获取Bean接口 * 可根据Bean名称,实时查找一个Bean */ Object getBean(String name) throws BeansException; /** * 可在实时查找Bean时,覆盖Bean的构造器参数,以此来获得参数自定义的Bean * Bean的作用域(scope)为原型(property)时使用,可在每次调用时动态调整参数 * Bean的作用域(scope)为单例(singleton)时使用,非常危险,每次调用同一个对象都会变动 * * @since 2.5 Spring 2.5引入 */ Object getBean(String name, Object... args) throws BeansException; }
- 根据Bean类型查找
- 实时查找
- 延迟查找
public interface BeanFactory { /** * 根据Bean的Class类型,实时查找一个Bean * * @since 3.0 Spring 3.0引入 */ <T> T getBean(Class<T> requiredType) throws BeansException; /** * 根据Bean的Class类型,延迟查找一个Bean, * 并在查找过程中,覆盖Bean构造器参数,不推荐使用 * * @since 4.1 Spring 4.1引入 */ <T> T getBean(Class<T> requiredType, Object... args) throws BeansException; //-------------以上为按类型实时查找,以下为按类型延迟查找---------- /** * 根据Bean的Class类型,延迟查找一个Bean * * @since 5.1 */ <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType); /** * 根据Bean的ResolvableType类型,延迟查找一个Bean, * * @since 5.1 */ <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType); }
延迟查找
延迟查找在getBean时,会先返回一个ObjectProvider
,而ObjectProvider
是ObjectFactory
的子类,通过调用ObjectFactory#getObject
方法获得Bean,这种通过二次查找,先拿到一个类似句柄的东西,通过句柄查找Bean的方式,就是延迟查找。
更多链接:BeanFactory
与ObjectFactory
的区别(待补充)
ResolvableType
ResolvableType是因为JDK5引入了泛型后,为处理泛型类型的查找而引入的新的类型概念
- 根据Bean名称+类型查找
public interface BeanFactory { /** * 根据Bean的名称与Class类型,实时查找一个Bean * */ <T> T getBean(String name, Class<T> requiredType) throws BeansException; }
List Lookup
List Lookup
:集合查找
集合类型依赖查找接口:ListableBeanFactory
和ApplicationContext
一样,继承了BeanFactory
,通过调用#getBeanFactory
再调用对应方法的方式,去实现单一Bean的查找
返回的集合不限于
List
,而是Map
+Collection
- 通过Bean类型查找
- 获取同类型Bean的名称列表
- 获取同类型Bean的实例列表
public interface ListableBeanFactory extends BeanFactory { //--------获取同类型Bean的名称列表--------- /** * 根据给定的Class类型,返回Bean的名称列表 */ String[] getBeanNamesForType(@Nullable Class<?> type); /** * 根据给定的ResolvableType类型,返回Bean的名称列表 */ String[] getBeanNamesForType(ResolvableType type); //--------获取同类型Bean的名称列表--------- /** * 根据给定的ResolvableType类型,返回Bean的实例列表 */ <T> Map<String, T> getBeansOfType(@Nullable Class<T> type) throws BeansException; /** * 根据给定的ResolvableType类型,返回Bean的实例列表 * @param type 指定的Bean Class类型 * @param includeNonSingletons 查找时是否包含非单例的,使用#getBeansOfType时为true * @param allowEagerInit 是否初始化FactoryBean中的实例,使用#getBeansOfType时为true */ <T> Map<String, T> getBeansOfType(@Nullable Class<T> type, boolean includeNonSingletons, boolean allowEagerInit) throws BeansException; }
- Spring3增加 - 通过注解类型查找
- 获取标注类型Bean的名称列表
- 获取标注类型Bean的实例列表
- 获取指定名称 + 标注类型Bean实例
public interface ListableBeanFactory extends BeanFactory { /** * 根据注解类型,返回带有该注解的Bean名称列表 * * @since 4.0 */ String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType); /** * 根据注解类型,返回带有该注解的Bean实例列表 * 是否想起了Aop根据是否带有注解来控制是否进行切面的功能 * * @since 3.0 */ Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) throws BeansException; /** * 根据Bean名称 + 注解类型,返回一个Bean实例列表 * 实际为上面两个功能的结合使用,源码中的@see文档注释也说明了这一点 * * @since 3.0 * @see #getBeanNamesForAnnotation * @see #getBeansWithAnnotation */ <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType) throws NoSuchBeanDefinitionException; }
Bean的名称和Bean的列表,谁重要?
调用#getBeans
相关的接口,会触发Bean的初始化,容易出现各种未知的错误
Hierarchical Lookup
Hierarchical Lookup
:层次性查找
层次性依赖查找接口:HierarchicalBeanFactory
和BeanFactoryUtils
HierarchicalBeanFactory
负责定义层次性,BeanFactoryUtils
负责提供辅助功能
应用程序可能会存在多个容器,当想要多个容器之间联合工作时,就需要用到层次性查找功能 - 将容器组合为父子容器
Spring的层次性查找,只会记录父容器,没有直接指向子容器的方法,采用的是类似于双亲委派的方式。
Spring会先查找子容器,再查找父容器,不同的是,父子容器都有的BeanDefinition,会优先取子容器的BeanDefinition
- 查找双亲BeanFactory:
#getParentBeanFactory
public interface HierarchicalBeanFactory extends BeanFactory { /** * 返回父容器,为空时说明已经是最顶层的容器 */ BeanFactory getParentBeanFactory(); }
- 根据Bean名称查找
public interface HierarchicalBeanFactory extends BeanFactory { /** * 判断是否存在Bean,只判断当前容器内的Bean * * @param name Bean的名称 */ boolean containsLocalBean(String name); } public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory { // 对应的子类方法实现 @Override public boolean containsLocalBean(String name) { //先将别名处理为真正的Bean名称,里面有一段代码很有趣 String beanName = transformedBeanName(name); //再逐个判断当前容器中的各个部分是否含有Bean return ((containsSingleton(beanName) || containsBeanDefinition(beanName)) && (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(beanName))); } //继续往下找 protected String transformedBeanName(String name) { return canonicalName(BeanFactoryUtils.transformedBeanName(name)); } //此时已经位于org.springframework.core.SimpleAliasRegistry#canonicalName public String canonicalName(String name) { String canonicalName = name; String resolvedName; //可能在通过别名的map找到一个名称时,这个名称依然是别名 //所以需要不断的循环,直到通过name找不到时才算真正的找到 //也就反向说明了,bean可以有多个别名 do { resolvedName = this.aliasMap.get(canonicalName); if (resolvedName != null) { canonicalName = resolvedName; } } while (resolvedName != null); return canonicalName; } }
- 根据Bean类型查找实例列表
- 单一类型
- 集合类型
public abstract class BeanFactoryUtils { //------------单一类型---------- /** * 根据类型,从指定工厂中获取一个Bean * 从实现上也可以看出,其实就是调用的ListableBeanFactory#getBeansOfType方法 * * @param lbf 可列举的Bean工厂 * @param Class<T> Bean的Class类型 */ public static <T> T beanOfType(ListableBeanFactory lbf, Class<T> type) throws BeansException { Assert.notNull(lbf, "ListableBeanFactory must not be null"); Map<String, T> beansOfType = lbf.getBeansOfType(type); return uniqueBean(type, beansOfType); } /** * 根据类型以及其他定义参数,从指定工厂中获取一个Bean * * @param type 指定的Bean Class类型 * @param includeNonSingletons 查找时是否包含非单例的,使用#getBeansOfType时为true * @param allowEagerInit 是否初始化FactoryBean中的实例,使用#getBeansOfType时为true */ public static <T> T beanOfType(ListableBeanFactory lbf, Class<T> type, boolean includeNonSingletons, boolean allowEagerInit) throws BeansException { Assert.notNull(lbf, "ListableBeanFactory must not be null"); Map<String, T> beansOfType = lbf.getBeansOfType(type, includeNonSingletons, allowEagerInit); return uniqueBean(type, beansOfType); } //------------集合类型---------- /** * 判断是否存在Bean,会判断当前容器与父容器 * * @param name Bean的名称 */ public static <T> T beanOfTypeIncludingAncestors(ListableBeanFactory lbf, Class<T> type)throws BeansException { Map<String, T> beansOfType = beansOfTypeIncludingAncestors(lbf, type); return uniqueBean(type, beansOfType); } /** * 找一个参数少的经典的例子来仔细看 * * @param lbf 需要拿值的容器 * @param Class<T> Bean的Class类型 */ public static <T> Map<String, T> beansOfTypeIncludingAncestors(ListableBeanFactory lbf, Class<T> type) throws BeansException { Assert.notNull(lbf, "ListableBeanFactory must not be null"); //初始化最终返回的Bean Map Map<String, T> result = new LinkedHashMap<>(4); //先将子容器内,属于该类型的Bean放入总结果集的Map中 //因为下面有递归调用,经过下面的操作,有可能含有父集的Bean,所以是总结果集 result.putAll(lbf.getBeansOfType(type)); //如果该容器可以分级查找 if (lbf instanceof HierarchicalBeanFactory) { HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf; //如果该容器含有父容器并且父容器是可列举的,instanceof碰到null不会空指针,而是判定为false if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) { //递归调用,对父容器使用同样的方法查找Bean,并获得Bean的返回Map parentResult Map<String, T> parentResult = beansOfTypeIncludingAncestors( (ListableBeanFactory) hbf.getParentBeanFactory(), type); //遍历父容器,当总结果集内不存在该Bean,并且当前容器内也不存在这个Bean时,将Bean加入总结果集中 //这里是根据Bean名称判断,而不是根据实例化的Bean,根据Bean的实例判断,会提前触发Bean的初始化,会产生很多未知的影响 //由此也可以看出,Bean是可以被覆盖的,子容器覆盖父容器相同Bean名称的Bean parentResult.forEach((beanName, beanInstance) -> { if (!result.containsKey(beanName) && !hbf.containsLocalBean(beanName)) { result.put(beanName, beanInstance); } }); } } //返回总的结果集 return result; } /** * 判断是否存在Bean,会判断当前容器与父容器 * * @param lbf 需要拿值的容器 * @param Class<T> Bean的Class类型 * @param includeNonSingletons 查找时是否包含非单例的,使用#getBeansOfType时为true * @param allowEagerInit 是否初始化FactoryBean中的实例,使用#getBeansOfType时为true */ public static <T> T beanOfTypeIncludingAncestors(ListableBeanFactory lbf, Class<T> type, boolean includeNonSingletons, boolean allowEagerInit) throws BeansException { Map<String, T> beansOfType = beansOfTypeIncludingAncestors(lbf, type, includeNonSingletons, allowEagerInit); return uniqueBean(type, beansOfType); } }
由
BeanFactoryUtils# beansOfTypeIncludingAncestors
方法可以看出,Bean的层级查找很像双亲委派原则,但是父子层级的选择优先级上又不同,双亲委派是优先取父容器内的对象,而Spring则是优先取子容器里的对象。
出现区别的原因主要还是因为两者的定位不同
JDK需要保证同一个类在不同地方对其的引用也是相同的,这样程序的类对象才能统一。
而Spring容器则是面向应用的,子应用很多时候需要对父应用的功能进行扩展,所以就得保证获得的Bean是自己自定义的,就和重写方法的调用原则很相似。
- 根据Java注解查找名称列表
public abstract class BeanFactoryUtils { /** * 根据特定条件,从指定容器中拿到Bean的名称列表 * 和上面的方法过程很类似,就不详细说了 * * @param lbf 需要拿值的容器 * @param Class<T> Bean的Class类型 * @param includeNonSingletons 查找时是否包含非单例的,使用#getBeansOfType时为true * @param allowEagerInit 是否初始化FactoryBean中的实例,使用#getBeansOfType时为true * @since 5.0 * @see ListableBeanFactory#getBeanNamesForAnnotation(Class) */ public static String[] beanNamesForAnnotationIncludingAncestors(ListableBeanFactory lbf, Class<? extends Annotation> annotationType) { Assert.notNull(lbf, "ListableBeanFactory must not be null"); String[] result = lbf.getBeanNamesForAnnotation(annotationType); if (lbf instanceof HierarchicalBeanFactory) { HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf; if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) { String[] parentResult = beanNamesForAnnotationIncludingAncestors( (ListableBeanFactory) hbf.getParentBeanFactory(), annotationType); result = mergeNamesWithParent(result, parentResult, hbf); } } return result; } }
在
HierarchicalBeanFactory
中,只有获取方法,没有设置方法,这是为什么呢?
我们来看下HierarchicalBeanFactory
的子接口ConfigurableBeanFactory
public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry {
/**
* 子接口ConfigurableBeanFactory
* 不仅继承了HierarchicalBeanFactory还继承了SingletonBeanRegistry
* 实际上是为了对设置方法的统一
* SingletonBeanRegistry → 单例bean的注册中心
* 从名称上也可以感受到 Configurable → 可配置的,就是将需要配置的东西抽离了出来
*
* @param parentBeanFactory 父容器
*/
void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateException;
}
Lazy Lookup
Lazy Lookup
:延迟查找
延迟查找类似于获取一个句柄,当句柄指向的Bean改变时,引用者不需要有其他操作
延迟加载类ObjectFactory
和ObjectProvider
不一定只含有一个Bean(虽然有的API只返回一个),有单独Bean的查找接口,也有Stream流形式的API提供查找或者处理功能。
在容器初始化阶段,有些Bean会在第一次加载时因为各种原因没有被完全加载(例如循环依赖),会将Bean在另一个阶段进行完全加载,这种方式就很像ObjectFactory
的延迟加载
延迟查找接口:ObjectFactory
和ObjectProvider
基础用法可参考Spring - Bean Definition - Base中的延迟初始化一节
以下为扩展的使用接口
/**
* @since 1.0.2
*/
public interface ObjectFactory<T> {
/**
* 返回这个工厂管理的一个单例或者原型的实例
*/
T getObject() throws BeansException;
}
/**
* @since 4.3
*/
public interface ObjectProvider<T> extends ObjectFactory<T>, Iterable<T> {
/**
* 继承的父类的方法,返回一个管理的实例
*/
T getObject(Object... args) throws BeansException;
/**
* 如果有的情况下返回一个对应的实例
*/
T getIfAvailable() throws BeansException;
/**
* 使用Lamdba对方法进行增强,没有Bean时可以返回一个自己控制的默认值
*/
default T getIfAvailable(Supplier<T> defaultSupplier) throws BeansException {
T dependency = getIfAvailable();
return (dependency != null ? dependency : defaultSupplier.get());
}
/**
* 使用Lamdba对方法进行增强,如果有Bean时,可以对Bean进行消费
*/
default void ifAvailable(Consumer<T> dependencyConsumer) throws BeansException {
T dependency = getIfAvailable();
if (dependency != null) {
dependencyConsumer.accept(dependency);
}
}
/**
* 增加的Lamdba流式操作,可以对方法进行增强,如果有Bean时,可以对Bean进行消费
* 子类DefaultListableBeanFactory 对其进行了实现
*/
default Stream<T> stream() {
throw new UnsupportedOperationException("Multi element access not supported");
}
}
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
/**
* 对ObjectProvider stream方法的实现,使其可以进行流式操作
*/
public Stream<Object> stream() {
return this.resolveStream(false);
}
}
方法使用示例
public class ObjectProviderDemo {
@Bean//方法名就是Bean名
public String helloWorld() {
return "Hello,World";
}
public static void main(String[] args) {
// 创建 BeanFactory 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 将类 ObjectProviderDemo 注册为配置类(Configuration Class)
applicationContext.register(ObjectProviderDemo.class);
// 启动应用上下文
applicationContext.refresh();
// 依赖查找集合对象
lookupByObjectProvider(applicationContext);
lookupIfAvailable(applicationContext);
lookupByStreamOps(applicationContext);
// 关闭应用上下文
applicationContext.close();
}
//流式操作
private static void lookupByStreamOps(AnnotationConfigApplicationContext applicationContext) {
ObjectProvider<String> objectProvider = applicationContext.getBeanProvider(String.class);
objectProvider.stream().forEach(System.out::println);
}
//含有默认值的查找
private static void lookupIfAvailable(AnnotationConfigApplicationContext applicationContext) {
ObjectProvider<User> userObjectProvider = applicationContext.getBeanProvider(User.class);
User user = userObjectProvider.getIfAvailable(User::createUser);
System.out.println("当前 User 对象:" + user);
}
//直接进行延迟依赖查找
private static void lookupByObjectProvider(AnnotationConfigApplicationContext applicationContext) {
ObjectProvider<String> objectProvider = applicationContext.getBeanProvider(String.class);
System.out.println(objectProvider.getObject());
}
}
Dependency lookup safely
此处讨论的安全性是指查找Bean时是否会抛出异常
依赖查找安全性对比
依赖查找类型 | 代表实现 | 是否安全 |
---|---|---|
单一类型查找 | BeanFactory#getBean | 否 |
ObjectFactory#getObject | 否 | |
ObjectProvider#getIfAvailable | 是 | |
集合类型查找 | ListBeanFactory#getBean | 是 |
ObjectProvider#stream | 是 |
当进行层次性查找时,安全性依赖于使用的BeanFactory
Built-in dependencies
Built-in dependencies
:内建依赖
tip Spring容器在启动时,会自动注入一些依赖,以供容器运行使用
AbstarctApplicationContext
:是ApplicationContext
的实现基类,定义了大量的容器上下文功能的基础实现。
此类的实现功能中,包括但不限于Annotation
、ConfigurationApplicationContext
、Web支持
,,所以会初始化相关的一些依赖
AbstarctApplicationContext
内建的依赖
Bean名称 | Bean实例 | 使用场景 |
---|---|---|
environment | Environment对象 | 外部化配置以及Profiles |
systemProperties | java.util.Propertie对象 | Java系统属性 |
systemEnvironment | java.util.Map对象 | 操作系统环境变量 |
messageSource | MessageSource对象 | 国际化文案 |
lifecycleProcessor | LifecycleProcessor对象 | Lifecycle Bean处理器 |
applicationEventMulitcaster | ApplicationEventMulitcaster对象 | spring事件广播 |
注解驱动下内建的依赖,使用xml或者注解的component-scan,或者显示使用ApplicationContext激活时,会内建以下依赖
Bean名称 | Bean实例 | 使用场景 |
---|---|---|
org.springframework.context.annotation. internalConfigurationAnnotationProcessor | ConfigurationClassPostProcessor对象 | 处理Spring配置类,控制BeanFactory的生命周期 |
org.springframework.context.annotation. internalAutowiredAnnotationProcessor | AutowiredAnnotationBeanPostProcessor对象 | 处理@Autowired以及@Value注解 |
org.springframework.context.annotation. internalCommonAnnotationProcessor对象 | CommonAnnotationBeanPostProcessor | 满足一定情况下,激活jsr-250注解,如:@PostConstruct |
org.springframework.context.event. internalEventListenerProcessor | EventListenerMethodProcessor对象 | 处理标记@EventListener的Spring事件监听方法 |
org.springframework.context.event. internalEventListenerFactory | DefaultEventListenerFactory对象 | @EventListener事件监听方法适配为ApplicationListener |
org.springframework.context.annotation. internalPersistenceAnnotationProcessor | PersistenceAnnotationBeanPostProcessor对象 | 满足一定条件的情况下,处理JPA注解 |
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor, PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
//实现了BeanDefinitionRegistryPostProcessor → BeanFactoryPostProcessor → BeanFactoryPostProcessor
//可以看出控制的是BeanFactory的生命周期
}
public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
//实现了InstantiationAwareBeanPostProcessorAdapter → SmartInstantiationAwareBeanPostProcessor
// → InstantiationAwareBeanPostProcessor → BeanPostProcessor
//所以控制的是Bean的生命周期
public AutowiredAnnotationBeanPostProcessor() {
this.autowiredAnnotationTypes.add(Autowired.class);
this.autowiredAnnotationTypes.add(Value.class);
try {
this.autowiredAnnotationTypes.add(ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
this.logger.info("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
} catch (ClassNotFoundException var2) {
}
}
}
public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBeanPostProcessor implements InstantiationAwareBeanPostProcessor, BeanFactoryAware, Serializable {
public CommonAnnotationBeanPostProcessor() {
this.setOrder(2147483644);
//处理公共注解
this.setInitAnnotationType(PostConstruct.class);
this.setDestroyAnnotationType(PreDestroy.class);
this.ignoreResourceType("javax.xml.ws.WebServiceContext");
}
}
public class DefaultEventListenerFactory implements EventListenerFactory, Ordered {
public ApplicationListener<?> createApplicationListener(String beanName, Class<?> type, Method method) {
//传入Bean名称、class类型、方法、将其转化为一个适配器(Adapter),由适配器,将方法信息转化为一个ApplicationListener,原来是这么对Bean方法进行监听的
return new ApplicationListenerMethodAdapter(beanName, type, method);
}
}
//以下即为注解驱动下,内建依赖的Bean名称以及对应的Bean
public abstract class AnnotationConfigUtils {
public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalConfigurationAnnotationProcessor";
public static final String CONFIGURATION_BEAN_NAME_GENERATOR = "org.springframework.context.annotation.internalConfigurationBeanNameGenerator";
public static final String AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalAutowiredAnnotationProcessor";
/** @deprecated */
@Deprecated
public static final String REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalRequiredAnnotationProcessor";
public static final String COMMON_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalCommonAnnotationProcessor";
public static final String PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalPersistenceAnnotationProcessor";
private static final String PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME = "org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor";
public static final String EVENT_LISTENER_PROCESSOR_BEAN_NAME = "org.springframework.context.event.internalEventListenerProcessor";
public static final String EVENT_LISTENER_FACTORY_BEAN_NAME = "org.springframework.context.event.internalEventListenerFactory";
private static final boolean jsr250Present;
private static final boolean jpaPresent;
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) {
//-----------------------------
//-------相当多的注册方法-------
//-----------------------------
}
}
以上仅为部分的内建对象,在Spring AOP 、Spring Boot中会有更多的内置对象,应该总结学习技巧,而不是背诵有哪些对象
Common Exception
依赖查找时,常见的一些异常
异常类型 | 触发条件 | 方法调用举例 |
---|---|---|
NoSuchBeanDefinitionException | 当查询的Bean在IoC容器中不存在时 | BeanFactory#getBean |
NoUniqueBeanDefinitionException | 依赖查找时出现多个匹配Bean | BeanFactory#getBean(Class) |
BeanInstantiationException | Bean所对应的类型不能被实例化、非具体类,(例如将接口或抽象类注册为Bean) | BeanFactory#getBean |
BeanCreationException | Bean初始过程中出现异常幷抛出 | @Postconstruct抛出异常 |
BeanDefinitionStoreException | BeanDefinition配置元信息非法 | XML资源无法访问到或无法打开,例如没有此XML或XML不可读 |
BeanException被设计为运行时异常,属于Spring设计上与JavaEE的区别点,因为Java抛出运行时异常,外层不需要强制进行try…catch
一点总结
一鼓作气、再而衰、三而竭,这篇文章写了两天,真的累了,写到后面实在是有心无力,并且因为长时间的坐着(上班 + 写文),早已坐得生疼、坐立不安,时间也已经到了2021年8月30日 23:56:06
,写不动了,以后有精力了再来继续补充改文章
编写中未完待续…
评论区