一步步读spring源码---使用idea工具编译spring/运行流程分析以及调试spring程序

一步步读spring

  • gradle编译spring5.0x源码
  • spring3.0中各个模块的作用
  • beanFactory
    • beanFactory的方法解释
      • ioc容器初始化的三个步骤
    • DI依赖注入
  • spring AOP
  • IOC入口
      • ctrl+alt+B 我们进到 它的具体实现上来,看它是整么实现的
  • spring中的异常工具类

gradle编译spring5.0x源码

  1. 下载gradle4.4.1.bin.zip,解压再配置环境变量
  2. https://services.gradle.org/distributions/
    
  3. 下载spring5.0x,再用gradle idea进行源码编译(如果是eclipse开发工具,可用gradle eclipse -x :eclipse)
  4. https://github.com/spring-projects/spring-framework/tree/5.0.x
    
  5. 等待编译完毕,用idea打开即可

spring3.0中各个模块的作用

aop--------------------Spring的面向切面编程,提供AOP(面向切面编程)实现

aspects---------------Spring提供对AspectJ框架的整合\

beans------------------SpringIoC(依赖注入)的基础实现

context.support--------Spring-context的扩展支持,用于MVC方面

context---------------Spring提供在基础IoC功能上的扩展服务,此外还提供许多企业级服务的支持,如邮件服务、任务调度、JNDI定位、EJB集成、远程访问、缓存以及各种视图层框架的封装等

core-------------------Spring3.0的核心工具包

expression-------------Spring表达式语言

instrument.tomcat------Spring3.0对Tomcat的连接池的集成

instrument------------Spring3.0对服务器的代理接口

jdbc-------------------对JDBC的简单封装

jms--------------------为简化JMS API的使用而作的简单封装

orm--------------------整合第三方的ORM框架,如hibernate,ibatis,jdo,以及 spring的JPA实现

oxm--------------------Spring 对Object/XMl的映射支持,可以让Java与XML之间来回切换

test--------------------对Junit等测试框架的简单封装

transaction-------------为JDBC、Hibernate、JDO、JPA等提供的一致的声明式和编程式事务管理

web.portlet-------------SpringMVC的增强

web.servlet-------------对JEE6.0 Servlet3.0的支持

web.struts--------------整合Struts的时候的支持

web--------------------SpringWeb下的工具包

原文链接:https://blog.csdn.net/mixika99/article/details/72723374

beanFactory

选择此处作为入口
org.springframework.context.support;
ClassPathXmlApplicationContext

public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
     

	private Resource[] configResources;
	protected Resource[] getConfigResources() {
     
		return this.configResources;
	}
	public ClassPathXmlApplicationContext(.........各种构造方法)

其继承关系的uml图如下:
一步步读spring源码---使用idea工具编译spring/运行流程分析以及调试spring程序_第1张图片

beanFactory的方法解释

// todo 从IOC中拿到单例
	Object getBean(String name) throws BeansException;
	
// todo 判断ioc中有bean吗
	boolean containsBean(String name);
	
// todo 是否单例 如果isSingleton,那么从容器中每次调用getBean方法,获取的都是同一个对象的实例,---单例模式
	boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

// todo 是否单例 如果isSingleton,那么从容器中每次调用getBean方法,获取的都是同一个对象的实例,---单例模式
	boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

// todo 如果isPrototype,那么每次(直接或间接)调用getBean方法,获取的都是一个新创建的对象。---原型模式
	boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

// todo 获得bean的class类型
	Class<?> getType(String name) throws NoSuchBeanDefinitionException;

// todo 获得bean的别名
	String[] getAliases(String name);

ioc容器初始化的三个步骤

  1. 定位 (找到下xml文件在哪里)

  2. 加载
    之后会使用dom4j解析,将xml解析结果保存成BeanDefination,进而存在内存中

  3. 注册
    使用抽象工厂,根据BeanDefination的内容去生产了----只是说明了bean,调用bean才会初始化bean

//
工厂是标准化输出产品,ioc就是hash map

调用getBean/lazy-init为true是会触发bean的初始化

DI依赖注入

spting是使用map形式创建的单例

package org.springframework.beans.factory.support

   public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
     

        protected <T> T doGetBean(
			final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly){
     }

spring中如果不声明bean的scope,则默认都是单例的

spring AOP

切面是有n个具有共同点的bean组成的集合
com.service.impl.* 就是一个切面

某个bean的某个方法 ------------切入点

一个包是一个切面,一个对象的方法是一个切入点,目标对象,被代理对象,连接点是调用方法时的规则,切面是大规则,连接点是小规则(详细规则),满足连接点规则,就会触发通知(调用代理的代码)。

IOC入口

AnnotationConfigApplicationContext 通过注解初始化spring环境
ClassPathXmlApplicationContext 通过xml初始化spring环境

public class AnnotationConfigApplicationContext extends GenericApplicationContext {
     
     	public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
     
		this();
		//this.beanDefinitionMap.put(beanName,beanDefination)   将annotatedClasses转beanDefination再装入map
		register(annotatedClasses);
		//最重要的方法,没有之一
		refresh();
	}
}

public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
     
    public GenericApplicationContext() {
     
        //spring工厂代码的核心实现类
		this.beanFactory = new DefaultListableBeanFactory();
		this.beanFactory.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
	}
}

refresh()方法:

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
     
		
    public void refresh() throws BeansException, IllegalStateException {
     
		synchronized (this.startupShutdownMonitor) {
     
		try {
     
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				//完成类的扫描,并处理@ImportResource("com.xxx")
				//@import(xxx.class)  @MapperScan
				//scan ---->  put map  ----> 执行 invokeBeanFactoryPostProcessors
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				//真正new 对象,需要去new 的单例
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
				}
}
}

这个finishBeanFactoryInitialization()方法里的

// Instantiate all remaining (non-lazy-init) singletons.  实例化对象,之前是先处理spring核心的对象
		beanFactory.preInstantiateSingletons();

ctrl+alt+B 我们进到 它的具体实现上来,看它是整么实现的

一步步读spring源码---使用idea工具编译spring/运行流程分析以及调试spring程序_第2张图片
断点调试设置成:只有当beanName.equals(“c”)才进入循环体

   //拿到map里的所有key
   	@Override
	public void preInstantiateSingletons() throws BeansException {
     
		if (logger.isDebugEnabled()) {
     
			logger.debug("Pre-instantiating singletons in " + this);
		}

		// 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.
		//符合规则的,就是加了注解的,可能需要实例化的bean,已完成扫描。。。。。
		//单例是缓存到map中的,而原型是不需要缓存的。因有lazy/scope  ,所以这里是可能需要
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		for (String beanName : beanNames) {
     
		    //相当于beanDefinitionMap.get(beanName)从map里拿到所有的bean
		    //autowire是处理注解开发
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
     
				if (isFactoryBean(beanName)) {
     
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
     
						final FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
     
							isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
											((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
     
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
     
							getBean(beanName);
						}
					}
				}
				else {
     
					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((PrivilegedAction<Object>) () -> {
     
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else {
     
					smartSingleton.afterSingletonsInstantiated();
				}
			}
		}
	}

一个xml中的或者类上的注解@Component,Scope,这些信息都会对应一个beanDefination,类名的小写是key,类所对应的beanDefination是value(相当能记录bean的更多信息的Class)

spring遵循开闭原则。提供了许多的方法,供外界访问(你可以和spring一起来共同完成这个过程--------只需要你的类实现BeanFactoryPostProcessor接口就可以参与beanFactory构建bean的过程中来,和spring一起工作,修改beanFactory,可以对map中选中的要new的东西进行偷梁换柱)

测试类

public class Test {
     
    public static void main(String args[]){
     
        AnnotationConfigApplicationContext
                annotationConfigApplicationContext
                =new AnnotationConfigApplicationContext(Appconfig.class);
     /*   for (City){
            RootBeanDefinition beanDefinition=new RootBeanDefinition();
            beanDefinition.setBeanClassName("city");
            beanDefinition.setBeanClass(CityService.class);
            beanDefinition.setScope("prototype");  //这里设置bean的类型是原型 模式
            beanDefinition.setLazyInit(true);
            ........
            map.put("city",beanDefinition);
            //AnnotationConfigApplicationContext代码上这就是上下文
            //初始spring的时候,这些组件(beanDefination,map)加在一起维持spring的正常工作,就叫上下文
        }*/
//        File("d:\\com\\xxx")
//               List list=file.list();
//        for(singleName:listName){
     
//            class.forName("singleName")
//        }

scan —>map.put()----->beanFactoryProcessor()处理

你得告知spring一个起点类,指定要扫描那些东西,才开始扫描,在起点类中加@component是然并卵的。起点类都没有,spring不知从何扫描起。

spring在未执行beanFactoryProcesser之前,就会放7个创世纪(spring用来开天劈地的 类)在beanMap里面

spring环境:defaultbeanFactory(bean工厂),beanFatoryPostProcessor(后置处理器),singlePool(单例池),beanDefination…为了配合aop或ioc这些功能,这些组件加在一起就构成了spring的环境

spring中的异常工具类

public abstract class Assert {
     
    public static void state(boolean expression, String message) {
     
		if (!expression) {
     
			throw new IllegalStateException(message);
		}
	}
	public static void isTrue(boolean expression, String message) {
     
		if (!expression) {
     
			throw new IllegalArgumentException(message);
		}
	}
	...........
}

beanFactory是一个装载bean的工厂
factoryBean是一个生产bean的bean,他是一个特殊的bean

//beanName的命名是否规范,有无乱码,特殊符号#,$,%....
final String beanName = transformedBeanName(name);

去掉断点的方法
在这里插入图片描述
一步步读spring源码---使用idea工具编译spring/运行流程分析以及调试spring程序_第3张图片
组件的集合—环境(spring容器是组件的集合,并不是单单指一个map—spring中用的是ConCunrrentMap,即源码中的命名是SingleObject,理解成单例池即可)
90%是单例 getBean==null 就
10%非单例
AnnotationConfigApplicationContext—父类----GenericApplicationContext–父类—AbstractApplicationContext–找到-----》refresh()方法----进入子方法-----》finishBeanFactoryInitialization(beanFactory);----进入子方法------》beanFactory.preInstantiateSingletons();------ctrl+alt+b查看该方法的具体实现—》
if (isEagerInit) {
getBean(beanName);
}
进到getBean(),再进到doGetBean()
来到了超级经典的Object sharedInstance = getSingleton(beanName);

bean是否

调试时查看临时变量
一步步读spring源码---使用idea工具编译spring/运行流程分析以及调试spring程序_第4张图片
调试模式下:查看栈帧和线程
一步步读spring源码---使用idea工具编译spring/运行流程分析以及调试spring程序_第5张图片

你可能感兴趣的:(spring)