Spring本地启动Main函数-AnnotationConfigApplicationContext

1、 AnnotationConfigApplicationContext功能

该类可以实现基于Java的配置类加载自定义在Spring的应用上下文的bean。

1.1 使用方式一:在构造方法中完成注册和刷新

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MessageConfiguration.class);
System.out.println(ctx.getBean("beanName"));)//根据bean的名字获得与之对应的实例。

public AnnotationConfigApplicationContext(Class... annotatedClasses) {
this();
this.register(annotatedClasses);
this.refresh();
}

1.2 使用方式二:扫描包路径下所有的配置类,最后刷新

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.scan("org.spring.springboot");
ctx.refresh();
可以直接以包名作为参数传入。
public AnnotationConfigApplicationContext(String... basePackages) {
this();
this.scan(basePackages);
this.refresh();
}

使用方式三:通过使用register方法具体到注册哪个配置类,最后刷新。

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(AppConfig.class);
ctx.refresh();

2、 分析AnnotationConfigApplicationContext

AnnotationConfigApplicationContext继承了GenericApplicationContext并实现了接口AnnotationConfigRegistry 

2.1 接口:AnnotationConfigRegistry注册方法和扫描方法。注解配置注册表。用于注解配置应用上下文的通用接口,
拥有一个注册配置类和扫描配置类的方法。


2.2 GenericApplicationContext通用应用上下文。
GenericApplicationContext 继承 AbstractApplicationContext 实现 BeanDefinitionRegistry,内部持有一个
DefaultListableBeanFactory实例,这个类实现了BeanDefinitionRegistry接口,可以在它身上使用任意的bean definition读取器。

2.2.1 AbstractApplicationContext
ApplicationContext接口的抽象实现,没有强制规定配置的存储类型,仅仅实现了通用的上下文功能。
这个实现用到了模板方法设计模式,需要具体的子类来实现其抽象方法。自动通过registerBeanPostProcessors()
方法注册BeanFactoryPostProcessor, BeanPostProcessor和ApplicationListener的实例用来探测bean factory里的特殊bean。


2.2.2 BeanDefinitionRegistry
用于持有像RootBeanDefinition和 ChildBeanDefinition实例的bean definitions的注册表接口。GenericApplicationContext
类中的实例DefaultListableBeanFactory实现了这个接口,它对这个接口的实现实际上是通过调用这个实例的相应方法实现的,
因此可以通过相应的方法向beanFactory里面注册bean。

源码:

public interface BeanDefinitionRegistry extends AliasRegistry {
void registerBeanDefinition(String var1, BeanDefinition var2) throws BeanDefinitionStoreException;

void removeBeanDefinition(String var1) throws NoSuchBeanDefinitionException;

BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException;

boolean containsBeanDefinition(String var1);

String[] getBeanDefinitionNames();

int getBeanDefinitionCount();

boolean isBeanNameInUse(String var1);
}

2.3 构造方法
AnnotatedBeanDefinitionReader——BeanDefinition解析器用来解析带注解的bean


2.3.1 AnnotatedBeanDefinitionReader的构造器
注解的条件判断器ConditionEvaluator
该方法在初始化的时调用,当配置的类上有@Conditional注解并且返回false的时候,容器就不处理该类
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)
这个是关键,注册AnnotationConfigProcessor

// 默认使用三个bean处理器
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
    registerAnnotationConfigProcessors(registry, (Object)null);
}
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet(8);
        RootBeanDefinition def;
        if (!registry.containsBeanDefinition("org.springframework.context.annotation.internalConfigurationAnnotationProcessor")) {
            def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"));
        }

        if (!registry.containsBeanDefinition("org.springframework.context.annotation.internalAutowiredAnnotationProcessor")) {
            def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalAutowiredAnnotationProcessor"));
        }

        if (jsr250Present && !registry.containsBeanDefinition("org.springframework.context.annotation.internalCommonAnnotationProcessor")) {
            def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalCommonAnnotationProcessor"));
        }

2.3.1.1 @Bean的分析
是在refresh的invokeBeanFactoryPostProcessors(beanFactory)阶段,核心方法是loadBeanDefinitionsForBeanMethod,该方法处理了各种各样的注解。
注解分析的关键方法loadBeanDefinitionsForBeanMethod
该方法具体实现对包括如下注解的处理。
autowire
initMethod
destroyMethod

是在refresh的invokeBeanFactoryPostProcessors(beanFactory)阶段,核心方法是loadBeanDefinitionsForBeanMethod,
该方法处理了各种各样的注解。
2.3.1.2 ConditionEvaluator:配置的类上有@Conditional注解并且返回false的时候,容器就不处理该类

2.3.1.3 @Autowired 重点关注AutowiredAnnotationBeanPostProcessor后置处理器。

2.3.1.4 当AutowiredAnnotationBeanPostProcessor 作为接口MergedBeanDefinitionPostProcessor的实现时
AutowiredAnnotationBeanPostProcessor后置处理器的方法调用栈postProcessMergedBeanDefinition
该方法是在AbstractAutowireCapableBeanFactory.java的doCreateBean中调用的。该方法是创建bean实例的核心方法:

  • 1)创建Bean的实例:createBeanInstance(beanName, mbd, args)
  • 在此后:applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName)
  • 调用AutowiredAnnotationBeanPostProcessor的方法postProcessMergedBeanDefinition
  • 2)populateBean;给bean的各种属性赋值
  • 3)initializeBean:初始化bean;

2.3.2 ClassPathBeanDefinitionScanner——bean的扫描器 用来扫描类


注册解析传入的配置类(使用类配置的方式进行解析)
调用容器的refresh方法初始化容器

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值