栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring Framework 源码阅读(一):Aware接口及其实现类的作用

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring Framework 源码阅读(一):Aware接口及其实现类的作用

Spring framework 源码阅读(一):Aware接口及其实现类的作用

上一篇博文中已经介绍过怎么去编译Spring framework源码了,其实很简单,无非就是下载依赖然后构建工具会自动build项目。

  • 编译 Spring framework 5.2.17源码 & 在源码中使用 ApplicationContext 获取定义的Bean

使用过Spring系列框架进行开发的朋友应该都知道Bean,它是Spring IOC(控制反转)或者说DI(依赖注入)的基本单位,Spring通过BeanFactory来管理Bean,使得我们不需要手动去实例化这些被依赖Bean,而是由Spring的BeanFactory去发现Bean之间的依赖关系,从而实现Autowired(自动注入);当然实现这些功能还是有点复杂的,从源码中也可以看出,这里只是简单的概述;看源码不能急躁,一步一步去探索,最后发现没有尽头(ㄒoㄒ)。

比如AbstractBeanFactory中的doGetBean方法中有实现Bean之间的依赖关系。

				RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				// 保证对当前bean所依赖的bean进行初始化。
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					for (String dep : dependsOn) {
						if (isDependent(beanName, dep)) {
						    // beanName和dep之间存在循环依赖关系
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
						registerDependentBean(dep, beanName);
						try {
							getBean(dep);
						}
						catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}
					}
				}

上面只是为了引出Bean以及BeanFactory的一些概念,实际上要复杂的多,博主也会在以后的博客中进行详细介绍。

很显然BeanFactory能够感知到Bean的存在(ApplicationContext(应用上下文)的实现类通过一些工具类来解析注解定义、类路径信息以及XML配置文件等Bean定义源来感知Bean,如AnnotationConfigApplicationContext中的AnnotatedBeanDefinitionReader、ClassPathBeanDefinitionScanner以及XmlWebApplicationContext中的XmlBeanDefinitionReader等),并且创建和管理这些Bean。

而Bean怎么感知到BeanFactory的存在呢?,我们定义一个Bean一般就直接加注解或者在XML配置文件中进行定义,但这些定义不会涉及到BeanFactory的信息,BeanFactory就像是一个黑盒子;那现在就有一个问题了,当我们定义的Bean需要BeanFactory的一些信息该怎么办呢?这就是Aware接口及其实现类干的事情了,而aware也有意识到的意思,也就是意识到BeanFactory某些信息的存在。

package org.springframework.beans.factory;


public interface Aware {}

英文的大概意思:

  • 一个起标记作用的超接口,指示Bean可以通过回调形式的方法得到特定框架对象的Spring容器的通知。实际的方法由各个子接口决定(根据需要),但通常只包含一个接受单个参数并且返回void的方法。
  • 仅仅实现Aware接口并不会提供默认功能。相反,处理必须显式地完成,例如在BeanPostProcessor接口中。参考ApplicationContextAwareProcessor中处理特定Aware接口回调的例子。

不需要深究BeanPostProcessor是什么,只需要知道在Bean调用初始化方法的前后会调用BeanPostProcessor中的方法,对Bean实现定制化的功能。

ApplicationContextAwareProcessor中的postProcessBeforeInitialization方法就是在Bean调用初始化方法的之前会被调用,该方法又会调用invokeAwareInterfaces方法,在该方法中就会调用Aware接口实现类中的接受单个参数并且返回void的方法。

class ApplicationContextAwareProcessor implements BeanPostProcessor {

	private final ConfigurableApplicationContext applicationContext;

	private final StringValueResolver embeddedValueResolver;


	
	public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
		this.applicationContext = applicationContext;
		this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
	}


	@Override
	@Nullable
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
				bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
				bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
			return bean;
		}

		AccessControlContext acc = null;

		if (System.getSecurityManager() != null) {
			acc = this.applicationContext.getBeanFactory().getAccessControlContext();
		}

		if (acc != null) {
			AccessController.doPrivileged((PrivilegedAction) () -> {
				invokeAwareInterfaces(bean);
				return null;
			}, acc);
		}
		else {
			invokeAwareInterfaces(bean);
		}

		return bean;
	}

	private void invokeAwareInterfaces(Object bean) {
		if (bean instanceof EnvironmentAware) {
			((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
		}
		if (bean instanceof EmbeddedValueResolverAware) {
			((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
		}
		if (bean instanceof ResourceLoaderAware) {
			((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
		}
		if (bean instanceof ApplicationEventPublisherAware) {
			((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
		}
		if (bean instanceof MessageSourceAware) {
			((MessageSourceAware) bean).setMessageSource(this.applicationContext);
		}
		if (bean instanceof ApplicationContextAware) {
			((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
		}
	}
}
 

EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware以及ApplicationContextAware都是Aware接口的子接口。

public interface ApplicationContextAware extends Aware {
	void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}

所以,在Bean调用初始化方法的前后,会有一些方法去调用Aware接口实现类中的方法,从而实现通过回调形式的方法得到特定框架对象的Spring容器的通知,这样Bean就可以获取到BeanFactory的一些信息了。

当然,还有一些Aware接口的子接口,比如BeanNameAware、BeanClassLoaderAware、BeanFactoryAware、ServletContextAware以及ServletConfigAware等,其实这些子接口,在Bean的整个生命周期中有所体现,以便让Bean感知BeanFactory的各种信息,实现特定的功能。而这些子接口的回调是在其他类中实现的,AbstractAutowireCapableBeanFactory抽象类和ServletContextAwareProcessor类中。

AbstractAutowireCapableBeanFactory抽象类(继承了AbstractBeanFactory抽象类):

	private void invokeAwareMethods(String beanName, Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof BeanNameAware) {
				((BeanNameAware) bean).setBeanName(beanName);
			}
			if (bean instanceof BeanClassLoaderAware) {
				ClassLoader bcl = getBeanClassLoader();
				if (bcl != null) {
					((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
				}
			}
			if (bean instanceof BeanFactoryAware) {
				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
			}
		}
	}

ServletContextAwareProcessor类(实现了BeanPostProcessor接口):

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		if (getServletContext() != null && bean instanceof ServletContextAware) {
			((ServletContextAware) bean).setServletContext(getServletContext());
		}
		if (getServletConfig() != null && bean instanceof ServletConfigAware) {
			((ServletConfigAware) bean).setServletConfig(getServletConfig());
		}
		return bean;
	}

到这里大家应该知道Aware接口及其实现类的作用了吧,其中的方法会在创建Bean的过程中被回调,设置一些BeanFactory中的信息。

在Spring framework 源码中创建一个子Module,在上一篇博客中已经介绍过了,这里就不赘述了。


IMessageService接口:

package com.kaven.service;

import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.context.ApplicationContextAware;

public interface IMessageService extends ApplicationContextAware, BeanFactoryAware {
	String getMessage();
}

实现类MessageServiceImpl:

package com.kaven.service.impl;

import com.kaven.service.IMessageService;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

@Service("message")
public class MessageServiceImpl implements IMessageService {
	@Override
	public String getMessage() {
		return "Hello Kaven";
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		System.out.println("----------------MessageServiceImpl----------------------");
		System.out.println("setApplicationContext");
		System.out.println(applicationContext.getBeanDefinitionCount());
		System.out.println(applicationContext);
		System.out.println("----------------MessageServiceImpl----------------------");
	}

	@Override
	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
		System.out.println("----------------MessageServiceImpl----------------------");
		System.out.println("setBeanFactory");
		System.out.println(beanFactory);
		System.out.println("----------------MessageServiceImpl----------------------");
	}
}

启动类Application:

package com.kaven;

import com.kaven.service.IMessageService;
import com.kaven.service.impl.MessageServiceImpl;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.env.Environment;

import java.util.Arrays;

@ComponentScan({"com.kaven"})
public class Application implements BeanNameAware, EnvironmentAware {
	public static void main(String[] args) {
		ApplicationContext context = new AnnotationConfigApplicationContext(Application.class);
		IMessageService service = (MessageServiceImpl) context.getBean("message");
		System.out.println(service.getMessage());
		System.out.println(context.getBeanDefinitionCount());
		Arrays.stream(context.getBeanDefinitionNames()).forEach(System.out::println);
		((Application)context.getBean("application")).print("Hello Kaven");
	}

	public void print(String str){
		System.out.println(str);
	}

	@Override
	public void setBeanName(String name) {
		System.out.println("---------Application----------");
		System.out.println(name);
		System.out.println("---------Application----------");
	}

	@Override
	public void setEnvironment(Environment environment) {
		System.out.println("---------Application----------");
		System.out.println(environment);
		System.out.println("---------Application----------");
	}
}

输出结果:

显然是可以的。

阅读源码需要耐心,一步一步进行Debug,每个人的理解不同,如果博主有说错的地方,欢迎大家指正。

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号