spring(四)——————从spring源码角度去解释前面的疑问

前面两篇文章,我们从mybatis-spring的插件包出发,探究如何将第三方框架集成到spring中,也知道了mybatis中使用了FactoryBean+ImportBeanDefifinitionRegistrar+@Import对mapper进行注入。

不过我们在前两篇文章中仍然遗留很多疑点,例如

1、ImportBeanDefifinitionRegistrar是在什么时机被调用的,怎么被回调的,为什么不能搭配@Compnent一起使用?

2、mybatis是如何扩展spring的扫描器的?(扫描自定义注解或某个包下的类),而spring本身又是如何扫描的?

3、FeactoryBean的工作原理是什么?

4、BeanFactoryPostProcess的工作原理?怎么回调的?回调时机?本身是如何注入到spring中的?其子类的原理和作用?可以获取修改beandefinition,为什么不能注册?为什么有List<BeanFactoryPostProcess>这个集合?

5、什么是但理财、BeanDefinitionMap、@import是如何工作的?

下面我们才算开始学习spring源码,我们可以带着这些疑问,从源码的角度去解释这些疑问。

-----------------------------------------------------------------------------------------

一、什么是spring容器?

 上面是spring官方对容器的一个解释:

BeanFactory接口提供了一种高级配置机制,能够管理任何类型的对象。ApplicationContext是BeanFactory的子接口,该子接口补充了下面的功能:

1、更容易与Spring的AOP特性集成

2、消息资源处理(用于国际化)

3、事件发布

4、应用程序层特定的上下文,如web应用程序中使用的WebApplicationContext。

    简而言之,BeanFactory提供了配置框架和基本功能,ApplicationContext添加了更多企业特定的功能。ApplicationContext是BeanFactory的一个完整超集。

 我们可以简单的总结spring容器:容器由spring多个组件组成(如各种后置处理器、扩展接口),用于管理任何类型对象,并提供多种应用功能。其主要存在两个分支:BeanFactory、ApplicationContext(两者都可以叫做spring的容器,只是提供的功能不同)。BeanFactory相当于一个标配版容器(提供了基本的对对象的管理),而ApplicationContext是选配豪华版容器(不仅提供了父接口的功能,还提供了依赖注入、各种注解扫描、更简单的aop集成、事件发布、国际化等等)。

Integrated lifecycle management----------------

Automatic BeanPostProcessor registration---------@Autowried等依赖注入功能

Automatic BeanFactoryPostProcessor registration-----------------

Convenient MessageSource access (for internationalization)------国际化功能

Built-in ApplicationEvent publication mechanism---------事件发布功能

我们从三个方面来举例两者的不同:(以ApplicationContext比BeanFactory多出了依赖注入、各种注解扫描、事件发布这三个功能举例)

1、依赖注入功能

2、注解扫描功能

3、事件发布功能(springboot中大量使用事件发布功能进行扩展)

代码实例:

1)、SpringContainerBean 

package com.spring.demo.container;


import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;


/**
 * 测试依赖注入、注解扫描、事件发布等功能
 * */
@Slf4j
@Component
public class SpringContainerBean implements InitializingBean {


	//1、测试能否进行依赖注入
    @Autowired
    C c;

	@Autowired
	ApplicationContext context;


    public SpringContainerBean(){
		System.out.println("create SpringContainerBean  Object");
    }

	//2、测试能否扫描到这个注解
	//3、context.publishEvent()----测试事件发布功能
    @PostConstruct
    public void  init(){
		System.out.println("SpringContainerBean init PostConstruct");
		context.publishEvent(new ABeanInitEvent(context));

	}

    @Override
    public void afterPropertiesSet() throws Exception {
		System.out.println("SpringContainerBean init afterPropertiesSet");
    }


}

2)、依赖注入的类C

@Component
@Slf4j
public class C {

    public C(){
		System.out.println("create c Object");
    }

}

3)、事件类

/**
 * 发布事件类不需要进行注入操作(监听的类需要进行注入操作)
 */
public class ABeanInitEvent extends ApplicationContextEvent {

	public ABeanInitEvent(ApplicationContext source) {
		super(source);
	}
}

4)、监听事件类

/**
 * 监听ABeanInitEvent事件(需要进行注入)
 * */
@Component
public class ABeanListener implements ApplicationListener<ABeanInitEvent> {
	@Override
	public void onApplicationEvent(ABeanInitEvent event) {
		System.out.println("event----" + event.getClass().getSimpleName());
	}
}

5)、ApplicationContext容器的启动配置类ContextConfig 

@Component
@ComponentScan("com.spring.demo.container")
public class ContextConfig {
}

现在我们可以使用两个不同的容器,看看他们的功能区分:

启动ApplicationContext容器

public class ApplicationContextTest {


    public static void main(String[] args) {

        //获取ApplicationContext容器(传入ContextConfig配置类是为了让其自动调用register、refresh方法,也可以不传手动调用这两个方法)
		//这个ContextConfig就是我们平常写的Application类
        AnnotationConfigApplicationContext conext = new AnnotationConfigApplicationContext(ContextConfig.class);
	}
}

查看打印结果:

启动BeanFactory容器

public class BeanFactoryTest {


    public static void main(String[] args) {

         DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
		BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(SpringContainerBean.class);
		AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
		beanFactory.registerBeanDefinition("springContainerBean", beanDefinition);
		//BeanFactory注册的bean默认都是懒加载,需要手动getBean才会进行初始化
		beanFactory.getBean(SpringContainerBean.class);

	}
}

查看打印结果:

 从上面的结果看到,BeanFatory容器确实不支持依赖注入(c构造方法没被打印),注解扫描(@

@PostConstruct注解方法没被执行),事件发布。但两者都支持对对象的基本管理(对对象进行注入,对实现了InitializingBean的方法调用)

那么BeanFatory既然本身没支持这些功能,我们可以自己给他扩展吗?

答案是可以的,例如我们以依赖注入功能为例,看看怎么实现:

我们先注释掉SpringContainerBean 的context代码

package com.spring.demo.container;


import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;


/**
 * 测试依赖注入、注解扫描、事件发布等功能
 * */
@Slf4j
@Component
public class SpringContainerBean implements InitializingBean {


	//1、测试能否进行依赖注入
    @Autowired
    C c;

	/*@Autowired
	ApplicationContext context;*/


    public SpringContainerBean(){
		System.out.println("create SpringContainerBean  Object");
    }

	//2、测试能否扫描到这个注解
	//3、context.publishEvent()----测试事件发布功能
   /* @PostConstruct
    public void  init(){
		System.out.println("SpringContainerBean init PostConstruct");
		context.publishEvent(new ABeanInitEvent(context));

	}*/

    @Override
    public void afterPropertiesSet() throws Exception {
		System.out.println("SpringContainerBean init afterPropertiesSet");
    }





}

修改BeanFactory代码:

public class BeanFactoryTest {


    public static void main(String[] args) {

         DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
		BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(SpringContainerBean.class);
		//builder.getBeanDefinition().setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
		AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
		beanFactory.registerBeanDefinition("springContainerBean", beanDefinition);


		BeanDefinitionBuilder builderC = BeanDefinitionBuilder.genericBeanDefinition(C.class);
		AbstractBeanDefinition beanDefinitionC = builderC.getBeanDefinition();
		beanFactory.registerBeanDefinition("c", beanDefinitionC);
		//@Autowired的依赖注入原理就是依靠这个AutowiredAnnotationBeanPostProcessor,所以我们把他交给容器即可
		AutowiredAnnotationBeanPostProcessor auto = new AutowiredAnnotationBeanPostProcessor();
		auto.setBeanFactory(beanFactory);
		beanFactory.addBeanPostProcessor(auto);
		//BeanFactory注册的bean默认都是懒加载,需要手动getBean才会进行初始化
		//beanFactory.getBean(C.class);
		beanFactory.getBean(SpringContainerBean.class);

	}
}

如果知道@Autowrited注解的源码,应该就能知道@Autowired的依赖注入原理就是依靠这个AutowiredAnnotationBeanPostProcessor,所以我们需要把他交给容器。

这里还要注意一点:我们是没有去手动getBean(C.class)的,并且所以BeanFactory注入的bean都是懒加载的,如果我们依赖注入成功,则会打印C类的构造方法。

此时我们看下打印结果,发现依赖注入的功能实现了:

 2、BeandefinitionMap?

前面说到一个对象被转化为一个BeanDefinition,然后基本会被put到BeandefinitionMap。而BeandefinitionMap存在两种BeanDefinition,一种spring自己内部的Beandefinition,一种我们通过spring的扩展注入的。

现在我们以ApplicationContex容器为例

1)、ApplicationContex容器中实例化了一个DefaultListableBeanFactory
从AnnotationConfigApplicationContext为入口:
new AnnotationConfigApplicationContext
------------------》this()构造方法(有父类会先调用父类构造方法)
------------------》父类GenericApplicationContext的构造方法
-----------------》父类中存在一个属性DefaultListableBeanFactory beanFactory;并且构造方法会赋值this.beanFactory = new DefaultListableBeanFactory();

实际上就是以DefaultListableBeanFactory(BeanFactory容器为壳进行扩展自己的功能)为壳。

2)、进入DefaultListableBeanFactory

进入DefaultListableBeanFactory后我们可以发现一个属性------>

/** Map of singleton and non-singleton bean names, keyed by dependency type. */
Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
其中key----bean的名字,values----某个类的Beandefinition对象

3)、开始断点查找扫描后BeanDefinition put进beanDefinitionMap的代码

经过不断debug,当我们执行完AnnotationConfigApplicationContext--->refresh();------>

invokeBeanFactoryPostProcessors()方法后beanDefinitionMap出现了我们自己注入的BeanDefinition对象

-----------------------invokeBeanFactoryPostProcessors()方法执行前

---------------------invokeBeanFactoryPostProcessors()方法执行后

 所以我们可以推断 invokeBeanFactoryPostProcessors()方法完成了对我们自己注入的对象的扫描+put beanDefinitionMap的过程(执行这个方法之前Map没有值)

------------------------------invokeBeanFactoryPostProcessors方法执行前各个BeanDefinition的含义

(即此时未扫描我们自己注入的对象/类)

我们先不进去invokeBeanFactoryPostProcessors方法看其扫描的原理,我们先来看看这几个BeanDefinition的用处:

contextConfig -> 这是我们自己注册的BeanDefinition,因为实例化容器时需要传入这个类,所以就一同被注入了。

下面则是spring内部注册的Beandefinition:

1)、internalConfigurationAnnotationProcessor -> 对应的ConfigurationClassPostProcessor

该类是spring中非常重要的类,完成了spring的大部分工作(这里不细讲)

2)、internalEventListenerFactory" -> 对应的类DefaultEventListenerFactory

3)、internalEventListenerProcessor" -> 对应的类EventListenerMethodProcessor

4)、internalAutowiredAnnotationProcessor-> 对应类AutowiredAnnotationBeanPostProcessor

解析1@Autowrited、@Value等注解依赖注入

5)、internalCommonAnnotationProcessor-> 对应的类CommonAnnotationBeanPostProcessor

解析@Resource注解依赖注入等功能,还有其他功能

这几个BeanDefinition是什么时候实例化出来的?

AnnotationConfigApplicationContext---》this()----->AnnotatedBeanDefinitionReader类的构造器

--->AnnotationConfigUtils类的registerAnnotationConfigProcessors()方法

	/**
	 * Register all relevant annotation post processors in the given registry.
	 * @param registry the registry to operate on
	 * @param source the configuration source element (already extracted)
	 * that this registration was triggered from. May be {@code null}.
	 * @return a Set of BeanDefinitionHolders, containing all bean definitions
	 * that have actually been registered by this call
	 */
	public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
			BeanDefinitionRegistry registry, @Nullable Object source) {

		DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
		if (beanFactory != null) {
			if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
				beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
			}
			if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
				beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
			}
		}

		Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);


//--------------------实例化BenDefinition
		if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {

//-------1、实例化出对应的BeanDefinition
			RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
			def.setSource(source);

//--------2、registerPostProcessor方法将其put到BeanDefinitionMap中
			beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
		if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
		if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition();
			try {
				def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
						AnnotationConfigUtils.class.getClassLoader()));
			}
			catch (ClassNotFoundException ex) {
				throw new IllegalStateException(
						"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
			}
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
		}

		if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
		}

		return beanDefs;
	}

put到BeanDefinitionMap中是在registerPostProcessor方法中执行的,调用链:

registerPostProcessor()
--->BeanDefinitionRegistry接口的registerBeanDefinition()方法
----->其实现类DefaultListableBeanFactory中将BeanDefinition put到BeanDefinitionMap中

下篇我们开始讲invokeBeanFactoryPostProcessors()方法怎么扫描我们自己注入的对象/类,然后put到BeanDefinitionMap中的。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值