Spring的ApplicationContext核心分析

发布时间 2024-01-04 18:07:15作者: zzusjw

跟着孙哥学Spring,b站:https://www.bilibili.com/video/BV185411477k/?spm_id_from=333.337.search-card.all.click


1.AnnotationConfigApplicationContext执行过程

public static void main(String[] args){
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
    UserService userService = (UserService) ctx.getBean("userServiceImpl");
    userService.register();
}

当Spring的AnnotationConfigApplicationContext启动时,它会执行以下步骤:

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
    this();
    register(componentClasses);
    refresh();
}

public AnnotationConfigApplicationContext() {
    this.reader = new AnnotatedBeanDefinitionReader(this);
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}

2.BeanDefinitionReader接口解析

1. 常见实现类

  • XmlBeanDefinitionReader:用于配置文件。
  • AnnotatedBeanDefinitionReader:用于注解。

2. 作用

  • BeanDefinition的创建有三种方式。
  • DefaultListableBeanFactory#registerBeanDefinition:维护beanDefinitionMap

BeanDefinition创建方式

  1. XML配置:

    <bean id="" class=""/>
    
  2. 使用@Component, @Configuration, @Service, @Controller, @Repository注解:

    AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
    
  3. 使用BeanDefinitionBuilder

    BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(Test1.class);
    

3.@Import的使用方式

1. 使用@Import注解普通Java类

@Import(User.class)

2. 使用ImportSelector

public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{User.class.getName()};
    }
}

3. 自定义ImportBeanDefinitionRegistrar

// step1: 自定义ImportBeanDefinitionRegistrar
public class MyImportRegiser implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //创建BD
        // <bean id="userDAO" class="com.xxxx.UserDAOImpl"/>
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MyFactoryBean.class);
        GenericBeanDefinition beanDefinition = (GenericBeanDefinition) builder.getBeanDefinition();
        //BD进行注册
        registry.registerBeanDefinition("userDAO",beanDefinition);
    }
}


// step2: 利用FactoryBean创建代理类
public class MyFactoryBean implements FactoryBean<UserDAO> {
    @Override
    public UserDAO getObject() throws Exception {

        UserDAO userDAO = (UserDAO) Proxy.newProxyInstance(MyFactoryBean.class.getClassLoader(),new Class[]{UserDAO.class},(Object proxy, Method method, Object[] args)->{
            System.out.println("这是DAO接口的实现类");
            return null;
        });

        return userDAO;
    }

    @Override
    public Class<?> getObjectType() {
        return UserDAO.class;
    }
}

// step3: 使用@Import(MyImportRegiser.class) 进行导入
@Configuration
@ComponentScan("com.mybatis")
@Import(MyImportRegiser.class)
public class AppConfig {
    
}

4.BeanPostProcessor 和 BeanFactoryPostProcessor详解

BeanPostProcessor概述

BeanPostProcessor接口允许我们在Spring容器实例化Bean时插入自己的逻辑。它定义了两个主要方法,分别在Bean初始化前后被调用:

public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("MyBeanPostProcessor.postProcessBeforeInitialization");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("MyBeanPostProcessor.postProcessAfterInitialization");
        return bean;
    }
}

BeanPostProcessor的重要实现类

1. AutowiredAnnotationBeanPostProcessor

这个后处理器负责处理@Autowired, @Value, 和 @Inject注解,确保这些注解正确地被应用和处理。

2. CommonAnnotationBeanPostProcessor

这个后处理器处理常用的JSR-250注解,例如@Resource@PostConstruct@PreDestroy,以及init-methoddestroy-method属性,还有InitializingBeanDisposableBean接口。

BeanFactoryPostProcessor概述

BeanFactoryPostProcessor允许我们在Spring容器实例化任何其他Bean之前修改或处理BeanDefinition。其中,最常用的实现类是ConfigurationClassPostProcessor

ConfigurationClassPostProcessor的作用

  1. 处理@Configuration注解:它负责处理带有@Configuration注解的类,并确保正确处理其中的@Bean方法。

  2. 处理@ComponentScan:这个后处理器也负责扫描带有@ComponentScan注解的类,并将其中的Bean定义注册到容器中。

  3. 处理@Import@ImportResource

    • @Import注解可以通过多种方式导入其他配置类或定义Bean。 1 注册普通类 2 importSelect 3 importBeanDefinitionRegister
    • @ImportResource注解允许我们导入XML配置文件中定义的Bean。
  4. 处理@PropertySource:这个注解允许我们在@Configuration类中指定外部属性文件,使其可以被Spring容器加载。