有开头没结尾
经历了java开发变迁史,从早期编写原生的servlet、自研mvc和jdbc工具、和使用开源框架struts、hibernate、jsp、spring、springmvc、freemarker、springboot,到最后前后端分离式开发,一开始开发工具用的是editplus。相对来说,现在开发很好了,框架生态(只有spring生态传承下来了,其他都成了历史)。到spring生态圈终结了,它的体系太过庞大了,席卷了各国,项目产品技术换型的几率很小了。
一开始做Spring相关开发,写了大量xml配置,到后来换成了注解式开发,虽然能干活,可并不知道它的内在原理和设计理念是什么,随着时间的累计,需要做sping 扩展或集成,就要研究源码级是如何实现的了。我就以一个Spring Bean如何创建开始,不要小看一个Bean,很多码农都说不清它的创建过程。
简单介绍Spring框架是一个开放源代码的J2EE应用程序框架,由Rod Johnson发起,是针对bean的生命周期进行管理的轻量级容器(lightweight container)。 Spring解决了开发者在J2EE开发中遇到的许多常见的问题,提供了功能强大IOC、AOP及Web MVC等功能。Spring可以单独应用于构筑应用程序,也可以和Struts、Webwork、Tapestry等众多Web框架组合使用,并且可以与 Swing等桌面应用程序AP组合。因此, Spring不仅仅能应用于JEE应用程序之中,也可以应用于桌面应用程序以及小应用程序之中。Spring框架主要由七部分组成,分别是 Spring Core、 Spring AOP、 Spring ORM、 Spring DAO、Spring Context、 Spring Web和 Spring Web MVC。
就是图片里的Beans,下面开始进入正题,看仔细了,这很重要
介绍bean之前,说下ioc和context上下文(可以理解为一个宿主环境)
ioc是Inversion of Control的简称,行内话叫控制反转,早期开发都是需要对象,自己new出来一个,可有了ioc后,我们不需要
自己new对象了,让spring ioc容器负责对象的创建和管理。一句话概括ioc的作用颠倒了对象的依赖关系,ioc容器管理对象。
尽量搞明白bean,ioc,context,对以后学spring生态很重要。
Spring bean 分两种,一种普通bean,一种是工厂型的bean,但处理类型很多
一, 普通bean(以xml配置为例,现在改用注解的人越来越多了)
准备好原材料
spring-bean.xml文件(以演示为例)
User.java
public class User {
private int id;
private String name;
private int age;
//set,get略
}
测试类
/**
*
* @author dgm
* @describe "xml bean"
* @date 2020年4月16日
*/
public class XMLConfigurationBeanApp {
public static void main(String[] args) {
/*DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions("conf/spring-bean.xml");*/
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("conf/spring-bean.xml");
User user1 = applicationContext.getBean("user", User.class);
User user2 = (User) applicationContext.getBean("user");
System.out.println(user1);
System.out.println(user2);
System.out.println(user1==user2);
//由于是个普通的bean,故出现异常,生成环境就不需要这样写了,我是测试两种不同类型的bean
System.out.println(applicationContext.getBean("&user"));
}
}
输出结果
解析初始化过程,就从这行代码
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("spring-bean.xml");
说起,看看spring做了多少事
三大阶段:bean解析,bean实例化,bean初始化,销毁
spring也是如此,一开始进行大量的xml文件解析工作,和java对应的类映射好
文件路径org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException
/**
* Actually load bean definitions from the specified XML file.
* @param inputSource the SAX InputSource to read from
* @param resource the resource descriptor for the XML file
* @return the number of bean definitions found
* @throws BeanDefinitionStoreException in case of loading or parsing errors
* @see #doLoadDocument
* @see #registerBeanDefinitions
*/
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
//xml文档解析
Document doc = doLoadDocument(inputSource, resource);
//调用注册bean定义
return registerBeanDefinitions(doc, resource);
}
}
文件路径org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
//调用bean注册
documentReader.registerBeanDefinitions(doc,
createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
。。。。。。嵌套很多
文件路径org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)
/**
* Process the given bean element, parsing the bean definition
* and registering it with the registry.
*/
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
//调用注册工具注册
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
文件路径org.springframework.beans.factory.support.DefaultListableBeanFactory.registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
BeanDefinition oldBeanDefinition;
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (this.logger.isWarnEnabled()) {
this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(oldBeanDefinition)) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
//终于测测成功了,一种数据结构
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
//同上
this.beanDefinitionMap.put(beanName, beanDefinition);
List updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (oldBeanDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
/** Map of bean definition objects, keyed by bean name */
private final Map beanDefinitionMap = new ConcurrentHashMap<>(256);
beanDefinition的部分属性,把它当然一种组装数据的结构就行
调用时
ClassPathXmlApplicationContext(AbstractApplicationContext).finishBeanFactoryInitialization(ConfigurableListableBeanFactory) line: 861
{
//部分代码
// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
@Override
public String resolveStringValue(String strVal) {
return getEnvironment().resolvePlaceholders(strVal);
}
});
}
// Instantiate all remaining (non-lazy-init) singletons.
//这里面东西可多了去了
beanFactory.preInstantiateSingletons();
}
preInstantiateSingletons核心代码:
@Override
public void preInstantiateSingletons() throws BeansException {
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
//工厂型bean(系统自带很多,当然也可以自己写),实现FactoryBean接口或继承AbstractFactoryBean
final FactoryBean> factory = (FactoryBean>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(new PrivilegedAction() {
@Override
public Boolean run() {
return ((SmartFactoryBean>) factory).isEagerInit();
}
}, getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
else {
//普通bean,人为实现,没有实现FactoryBean接口或没有继承AbstractFactoryBean
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry
/** Cache of singleton objects: bean name --> bean instance */
private final Map singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of singleton factories: bean name --> ObjectFactory */
private final Map> singletonFactories = new HashMap<>(16);
/** Cache of early singleton objects: bean name --> bean instance */
private final Map earlySingletonObjects = new HashMap<>(16);
/** Set of registered singletons, containing the bean names in registration order */
private final Set registeredSingletons = new LinkedHashSet<>(256);
注意篇幅有限: 列了一些核心方法,其实还有很多,由于代码量超超多,就不贴了
工厂型bean
该Bean实现了FactoryBean接口
public class UserFactoryBean implements FactoryBean {
private User user;
/**
* @return the user
*/
public User getUser() {
return user;
}
/**
* @param user the user to set
*/
public void setUser(User user) {
this.user = user;
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
*/
@Override
public Class> getObjectType() {
return user.getClass();
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.FactoryBean#getObject()
*/
@Override
public User getObject() throws Exception {
// TODO Auto-generated method stub
return user;
}
}
它和上面没有实现FactoryBean接口的处理方式不太一样,大体上相同不再赘述
/**
* Obtain an object to expose from the given FactoryBean.
* @param factory the FactoryBean instance
* @param beanName the name of the bean
* @param shouldPostProcess whether the bean is subject to post-processing
* @return the object obtained from the FactoryBean
* @throws BeanCreationException if FactoryBean object creation failed
* @see org.springframework.beans.factory.FactoryBean#getObject()
*/
protected Object getObjectFromFactoryBean(FactoryBean> factory, String beanName, boolean shouldPostProcess) {
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
object = doGetObjectFromFactoryBean(factory, beanName);
// Only post-process and store if not put there already during getObject() call above
// (e.g. because of circular reference processing triggered by custom getBean calls)
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (object != null && shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
}
this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
}
}
return (object != NULL_OBJECT ? object : null);
}
}
else {
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (object != null && shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
3.1 和初始化InitializingBean对应的DisposableBean接口,
3.2 自定义方法,destroy-method="destroyXML"
3.3 和@PostConstruct对应的 @PreDestroy
销毁顺序如图
代码就不举例了。
总结:其实你可以new User(6,"dongguangmming",99),但和spring没关系,Spring很强大,各个阶段都有机会改造参与bean的过程,组合度也很高,****BeanDefinitionRegistryPostProcessor,***BeanPostProcessor,***BeanFactory,****BeanFactoryPostProcessor
记住Spring bean:解析注册,实例化,初始化,销毁,才能做扩展性开发或集成第三方组件(比如mybatis,dubbo,email,zk,redis等)到spring的生态圈里
参考:
1. spring bean是什么 https://www.awaimai.com/2596.html
2 what-in-the-world-are-spring-beans https://stackoverflow.com/questions/17193365/what-in-the-world-are-spring-beans
4. Detailed tutorial on Redis caching in the SpringBoot series https://laptrinhx.com/detailed-tutorial-on-redis-caching-in-the-springboot-series-3352915639/
5. Spring Bean creation process http://www.programmersought.com/article/55942589567/
6. Inversion of Control Containers and the Dependency Injection pattern https://martinfowler.com/articles/injection.html
7. Spring bean Lifecycle Callbacks https://jstobigdata.com/spring/spring-bean-lifecycle-callbacks/
8. Spring BeanPostProcessor to customize beans https://jstobigdata.com/spring/spring-beanpostprocessor-to-customize-beans/