spring 知识点

Table of Contents

@Configuration的原理

@Autowired 和@Value 怎么自动注入的

step1

step2

step3

@Conditional实现原理

@Import 

1 Bean以class形式导入

2 实现ImportSelector,返回Bean路径

3 实现 ImportBeanDefinitionRegistrar 导入逻辑在继承类registerBeanDefinitions实现


本人最近理下spring源码,部分知识小碎知识点,记录一下,欢迎斧正,可能不太详细,勿喷!

@Configuration的原理

一个类加上@Configuration,类似于基于配置文件空配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

</beans>

然后可以在类里边 添加 @Bean、@Import...等注解,可以理解为在上述空配置文件中添加元素

在加载基于注解的spring容器(如AnnotationConfigApplicationContext)时 ,会循环执行BeanFactoryPostProcessor postXXX方法,其中org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry会对@Bean等注解 解析并添加到BeanDefineMap中以便后续实例化

默认会解析一下五类注解

@PropertySource

@ComponentScan

@Import

@ImportResource

@Bean

@Autowired 和@Value 怎么自动注入的

step1

spring在解析@PropertySource时 会按照配置路径将.properties或者.yml文件解析到

org.springframework.core.env.MutablePropertySources#propertySourceList中,

step2

在createBean时populateBean()设置属性时,在循环执行InstantiationAwareBeanPostProcessor  postXXX方法时,其中org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues方法就是用来注入加这两个注释的属性的,

step3

配置文件中配置的都是字符串,在注入属性时,spring会匹配适合对应类型转换的属性编辑器,如果有特殊需求,可自定义,属性编辑器,

eg.

public class DatePropertyEditor extends PropertyEditorSupport {
    private String format = "yyyy-MM-dd";
    public void setForrnat(String format) {
        this.format = format;
    }
    @Override
    public void setAsText(String argO) throws IllegalArgumentException {
        System.out.println("argO:" + argO);
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        try {
            Date d = sdf.parse(argO);
            this.setValue(d);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}
注册到BeanFactory中
@Component
public class MyBeanFactoryAware implements BeanFactoryAware {
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        DefaultListableBeanFactory bf= (DefaultListableBeanFactory) beanFactory;
        bf.registerCustomEditor(Date.class, DatePropertyEditor.class);
    }
}

value注入
@Component
public class TestA {
    @Value("2019-01-01")
    private Date date;
}
public static void main(String[] args) {
    AnnotationConfigApplicationContext ctx1 = new AnnotationConfigApplicationContext(MainConfig.class);
    TestA testA = (TestA) ctx1.getBean("testA");
    System.out.println(testA);
}

 

@Conditional实现原理

接上 "@Autowired 和@Value 怎么自动注入的"

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues 在注入@Bean 会根据@Conditional配置判断,该Bean是否应该跳过, 类似的有一系列的注解@ConditionalOnClass..

eg.

@Configuration
public class MainConfig {
    @Bean
    @Conditional(value = MyCondition.class)
    public MyLog getLog() {
        return new MyLog();
    }
}


public class MyCondition implements Condition {

    /**
     *
     * @param context
     * @param metadata
     * @return 返回true Bean注入,否则不注入
     */
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //判断容器中是否有myAspect的组件
        if(context.getBeanFactory().containsBean("myAspect")) {
            return true;
        }
        return false;
    }
}

@Import 

作用:向容器中导入Bean

@Import  有三种引入方式

@Import(value = {Person.class,MyImportSelector.class, MyBeanDefinitionRegister.class})

1 Bean以class形式导入

public class Person {
    ...
}

2 实现ImportSelector,返回Bean路径

public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.testimport.compent.Dog"};
    }
}

springBoot 的AutoConfiguration就是通过这种形式导入的,具体可以查阅 springBoot SPI机制

3 实现 ImportBeanDefinitionRegistrar 导入逻辑在继承类registerBeanDefinitions实现

public class MyBeanDefinitionRegister implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Cat.class);
        registry.registerBeanDefinition("cat",rootBeanDefinition);
    }
}

通过以上三种形式,将导入的Bean 加入到BeanDefine中,以待容器刷新时注入

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值