Spring核心逻辑

502 阅读10分钟

IOC 原理

运行代码架构图

       new ClassPathXmlApplicationContext("spring-ioc.xml");
         ClassPathXmlApplicationContext(configLocation, new AutowireCapableBeanFactory());
            AbstractApplicationContext.refresh();
                ClassPathXmlApplicationContext.loadBeanDefinitions(beanFactory);
                    AbstractBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader();
        			beanDefinitionReader.loadBeanDefinitions(configLocation);
        				doLoadBeanDefinitions(inputStream);
        				    processBeanDefinition(ele)
        				        processProperty(ele, beanDefinition);
        						beanDefinition.setBeanClassName(className);
        						getRegistry().put(name, beanDefinition)
        			beanFactory.registerBeanDefinition
                AbstractApplicationContext.registerBeanPostProcessors(AbstractBeanFactory beanFactory)
                	List beanPostProcessorList = beanFactory.getBeansForType(BeanPostProcessor.class)
                	beanFactory.addBeanPostProcessor((BeanPostProcessor)beanPostProcessor);
     HelloService helloService = (HelloService)applicationContext.getBean("helloService")
     	AbstractApplicationContext.getBean(String name)
     	    beanFactory.getBean(name)
     	       BeanDefinition beanDefinition = beanDefinitionMap.get(name);
               Object bean = beanDefinition.getBean();
               bean = doCreateBean(beanDefinition);
                   Object bean = beanDefinition.getBeanClass().newInstance();
        		   beanDefinition.setBean(bean);
                   AutowireCapableBeanFactory.applyPropertyValues(bean, beanDefinition);
               bean = initializeBean(bean, name);
               	    for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
            			bean = beanPostProcessor.postProcessBeforeInitialization(bean, name);
        			}
        			for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
            			bean = beanPostProcessor.postProcessAfterInitialization(bean, name);
        			}

1.BeanPostProcessor 后置处理器

 BeanPostProcessor 是一个接口的定义,里面只有两个接口。
    postProcessBeforeInitialization
    postProcessAfterInitialization

后置处理器需要实现这个接口,并把该实现类加入到bean容器中。成为一个bean对象。
根据是否都继承自BeanPostProcessor.class isAssignableFrom 找出满足的bean对象。
放入beanPostProcessors的list列表中。 在bean创建成功之后,调用后置处理器initializeBean。循环执行里面的每一个后置处理器。
每个后置处理器需要把bean对象返回,否则通过getBean拿不到对象。

    BeanDefinition beanDefinition = beanDefinitionMap.get(name);
        if (beanDefinition == null) {
            throw new Exception("No bean named " + name + " is defined");
        }
        Object bean = beanDefinition.getBean();
        if (bean == null) {
            bean = doCreateBean(beanDefinition);
            bean = initializeBean(bean, name);
        }
    return bean;

2.spring 4.2.4版本后置处理器逻辑

在AbstractAutowireCapableBeanFactory class 中
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException
在doCreateBean方法中
    BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
		Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);

		// Allow post-processors to modify the merged bean definition.
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				mbd.postProcessed = true;
			}
		}

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName, new ObjectFactory<Object>() {
				@Override
				public Object getObject() throws BeansException {
					return getEarlyBeanReference(beanName, mbd, bean);
				}
			});
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			populateBean(beanName, mbd, instanceWrapper);
			if (exposedObject != null) {
				exposedObject = initializeBean(beanName, exposedObject, mbd);
			}
		}
		catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			}
			else {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}

populateBean 是初始化bean的属性,initializeBean是完成bean的后置处理器。

before 与 after中间仅多了一个初始化方法init-method。

       Object wrappedBean = bean;
	   if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}

		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

3.spring的singleton与prototype

当bean对象从xml读取到beanDefinition,若scope配置是空的,则在生成bean实例的时候,判断scope类型,若是原型,则是单例类型则生成对象。如果是空
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				if (isFactoryBean(beanName)) {
					final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
					boolean isEagerInit;
					if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
						isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
							@Override
							public Boolean run() {
								return ((SmartFactoryBean<?>) factory).isEagerInit();
							}
						}, getAccessControlContext());
					}
					else {
						isEagerInit = (factory instanceof SmartFactoryBean &&
								((SmartFactoryBean<?>) factory).isEagerInit());
					}
					if (isEagerInit) {
						getBean(beanName);
					}
				}
				else {
					getBean(beanName);
				}
			}

如上代码所示,getMergedLocalBeanDefinition会获取bean的定义信息。
若scope定义的时候为空,则有下面的逻辑处理。可见默认是单例模式。

    // Set default singleton scope, if not configured before.
	if (!StringUtils.hasLength(mbd.getScope())) {
	    mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
	}

spring模拟的代码参考 github.com/zhangjeff/s…

AOP 原理

先看下AOP的几个名词解释

1.通知Advice: 定义了在切入点pointcut里面定义的程序点具体要做的操作和处理,它通过before,after和around来区别是在每个切入点之前、之后还是代替执行的代码。
2.切入点Pointcut: 表示一组连接点joinpoint,这些连接点或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的操作处理通知Advice将要发生的地方。
3.目标对象Target:代理的目标对象,即切面要被应用到的目标对象。
4.通知器Advisor:当完成对目标对象方法的增强行为操作(Advice)和切入点Point的设计开发之后,需要一个对象将目标对象、增强行为和切入点三者结合起来,通知器Advisor就是一个实现这个功能的对象,即通过Advisor通知器,可以定义哪些目标对象的哪些方法在什么地方使用这些增强行为。

AspectJAwareAdvisorAutoProxyCreator是Spring的BeanPostProcessor,一个后置处理器,所有的bean都会经过该后置处理器拦截,如果匹配Pointcut切面的则会返回代理类。代码如下。

public Object postProcessAfterInitialization(Object bean, String beanName) throws          Exception {
       if (bean instanceof AspectJExpressionPointcutAdvisor) {
           return bean;
       }
       if (bean instanceof MethodInterceptor) {
           return bean;
       }
       List<AspectJExpressionPointcutAdvisor> advisors = beanFactory
               .getBeansForType(AspectJExpressionPointcutAdvisor.class);
       for (AspectJExpressionPointcutAdvisor advisor : advisors) {
           if (advisor.getPointcut().getClassFilter().matches(bean.getClass())) {
               ProxyFactory advisedSupport = new ProxyFactory();
               advisedSupport.setMethodInterceptor((MethodInterceptor) advisor.getAdvice());
               advisedSupport.setMethodMatcher(advisor.getPointcut().getMethodMatcher());

               TargetSource targetSource = new TargetSource(bean, bean.getClass(), bean.getClass().getInterfaces());
               advisedSupport.setTargetSource(targetSource);

               return advisedSupport.getProxy();
           }
       }
       return bean;
   }

Spring的Aop主要分为两种,CGLIB和jdk动态代理,动态代理都是在运行过程中生成出来的。

jdk动态代理采用的是反射机制实现接口的代理。在调用具体方法前调用InvokeHandler来处理。
看一个jdk动态代理的实例

接口

public interface Subject {

   void rent();

   void hello(String str);
}   

实现类

public class RealSubject implements Subject {
    @Override
    public void rent() {
        System.out.println("I want to rent my house");
    }

    @Override
    public void hello(String str) {
        System.out.println("hello: " + str);
    }
}

实现InvokeHandler的实现类

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class DynamicProxy implements InvocationHandler {

    private Object subject;

    public DynamicProxy(Object subject) {
        this.subject = subject;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before rent house");

        System.out.println("Method:" + method);

        method.invoke(subject, args);
        System.out.println("after rent house");
        return null;
    }
}

客户端

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Client {
    public static void main(String[] args) {
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
        Subject realSubject = new RealSubject();
        InvocationHandler handler = new DynamicProxy(realSubject);
        Subject subject = (Subject) Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject
                .getClass().getInterfaces(), handler);

        System.out.println(subject.getClass().getName());
        subject.rent();
    }
}

当设置属性“sun.misc.ProxyGenerator.saveGeneratedFiles”,设置为true的时候。 可以生成新生成的代理类$Proxy0。

public final class $Proxy0 extends Proxy implements Subject {
    private static Method m1;
    private static Method m4;
    private static Method m2;
    private static Method m3;
    private static Method m0;

    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }
    
    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final void rent() throws  {
        try {
            super.h.invoke(this, m4, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final void hello(String var1) throws  {
        try {
            super.h.invoke(this, m3, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m4 = Class.forName("com.jeff.jdkaopExample.Subject").getMethod("rent");
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m3 = Class.forName("com.jeff.jdkaopExample.Subject").getMethod("hello", Class.forName("java.lang.String"));
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}
所以当调用真是的接口的时候,会调用到代理类$Proxy0的rent()接口,该接口的内容是super.h.invoke(this, m4, (Object[])null); 即调用proxy的h(InvocationHandler),该示例应该是 DynamicProxy实现,调用invoke方法,及调用DynamicProxy的invoke方法。

public Object invoke(Object proxy, Method method, Object[] args) 接口中第一个参数proxy的作用,一般情况下,没什么作用,从实际调用传入的参数可以看到,在生成的代理类中传入的是当前的代理类this,所以当调用方法,返回proxy的时候,实际返回的是代理对象,跟参数名称proxy含义一致。这种当在方法支持链式调用的时候可以进行链式调用。
CGLIB动态代理采用的是asm开源包,对代理类的class文件加载进来,通过修改其字节码生成子类来处理。
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(UserDaoImpl.class);
        enhancer.setCallback(new MethodInterceptor(){
            @Override
            public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
                System.out.println("this is CGlib test");
                return proxy.invokeSuper(obj, args);
            }
        });
        UserDaoImpl userDao = (UserDaoImpl)enhancer.create();
        userDao.query("张三");
如上代码是CGLIB的核心,调用的是enhance增强。callback的函数需要实现MethodInterceptor接口。

Spring bean循环依赖

当Spring有两个bean相互依赖的时候,没有一个bean在产生的时候能走完一个完整的生命周期。所以需要bean在完成完整的生命周期之前暴露bean的对象,否则就会形成死循环。暴露的不是一个半成品的bean,而是一个bean工厂,可以继续完成bean的postprossess等后置处理器。

暴露一个工厂的目的是为了提供一个完整的bean,真实调用的时候,工厂返回bean的时候会把这个bean的后置处置器都完整的执行。 "getEarlyBeanReference",他的javadoc是,尤其是为解决循环依赖的。

Obtain a reference for early access to the specified bean, typically for the purpose of resolving a circular reference.
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
   	Object exposedObject = bean;
   	if (bean != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
   		for (BeanPostProcessor bp : getBeanPostProcessors()) {
   			if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
   				SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
   				exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
   				if (exposedObject == null) {
   					return exposedObject;
   				}
   			}
   		}
   	}
   	return exposedObject;
   }

// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName, new ObjectFactory<Object>() {
				@Override
				public Object getObject() throws BeansException {
					return getEarlyBeanReference(beanName, mbd, bean);
				}
			});
		}

调用的地方

  Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
	}
    protected void beforeSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}
    }

spring的三级缓存,也就是三个Map集合类: singletonObjects:第一级缓存,里面放置的是实例化好的单例对象; earlySingletonObjects:第二级缓存,里面存放的是提前曝光的单例对象; singletonFactories:第三级缓存,里面存放的是要被实例化的对象的对象工厂。 所以当一个Bean调用构造函数进行实例化后,即使属性还未填充,就可以通过三级缓存向外暴露依赖的引用值(所以循环依赖问题的解决也是基于Java的引用传递),这也说明了另外一点,基于构造函数的注入,如果有循环依赖,Spring是不能够解决的。还要说明一点,Spring默认的Bean Scope是单例的,而三级缓存中都包含singleton,可见是对于单例Bean之间的循环依赖的解决,Spring是通过三级缓存来实现的。

spring的aware接口的支持

当bean继承接口ApplicationContextAware的时候,对应的bean是可以拿到applicationContext

实现原理

1.在AbstractApplicationContext.refresh()方法中当运行到

ApplicationContextAwareProcessor是一个bean的后置处理器,在bean被初始化后,就会实现该后置处理器。

public ApplicationContextAwareProcessor(ConfigurableApplicationContext    applicationContext) {
		this.applicationContext = applicationContext;
	}

刚才已经把applicationContext给放置到了该后置处理器。

  postProcessBeforeInitialization中
  invokeAwareInterfaces(bean);
  if (bean instanceof ApplicationContextAware) {
				((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
   }

通过以上步骤,只要bean继承了ApplicationContextAware 就能获取到applicationContext。

Spring的annotation实现

核心逻辑是AnnotationConfigApplicationContext 是其中的一种applicationContext的实现,会扫描提供的文件夹的文件,然后根据文件夹里面文件内容,再判断里面的类型,读取之后放到BeanDefinition中,放在BeanDefinitionHolder中,最后把该内容注册到beanFactory中,之后的逻辑就与xml的一致了。
@Component,@Service,@Repository,@Controller区别, @Component是一个通用的标签。当判断需要注入的时候,判断标签是否引用了@Component 标签。

其他几种类似。

spring源码中判断标签是否含有元标签Component,还有的才会加入到BeanDefinition中。

FactoryBean的作用

Spring中有两种类型的Bean,一种是普通的Bean,另一种是工厂Bean。即FactoryBean。FactoryBean跟普通的Bean不同,其返回的对象不是指定一个实例,而是该FactoryBean的getObject方法所返回的对象。
一般情况下,Spring通过反射机制,利用bean的class属性指定实现类的实例化Bean,在某些情况下,实例化Bean的过程比较复杂,如果按照传统的方式,则需要再bean中提供大量的配置信息。配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。Spring为此提供了一个FactoryBean的工厂类接口,可以通过实现该接口定制实例化Bean的逻辑。FactoryBean对spring框架来说占用重要的地位,它隐藏了实例化的一些复杂的bean的细节,给上层应用带来了便利。
很多开源项目在集成Spring 时都使用到FactoryBean,比如 MyBatis3 提供 mybatis-spring项目中的 org.mybatis.spring.SqlSessionFactoryBean:

如上图所示,普通的bean,走到红框的位置的时候,就返回了。FactoryBean会继续向下,调用当前bean的Object方法。

spring的观察者模式,发布-订阅。
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
    getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
   AbstractApplicationContext中 refresh() -> initApplicationEventMulticaster();中作用
    protected void initApplicationEventMulticaster() {
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
			this.applicationEventMulticaster =
					beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
			if (logger.isDebugEnabled()) {
				logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
			}
		}
		else {
			this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
			beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
			if (logger.isDebugEnabled()) {
				logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
						APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
						"': using default [" + this.applicationEventMulticaster + "]");
			}
		}
	}
     Initialize the ApplicationEventMulticaster.
	 Uses SimpleApplicationEventMulticaster if none defined in the context.

从注释上也可以看出,如果自定义了applicationEventMulticaster的实现类,则直接用自定义
的,否则用默认的实现SimpleApplicationEventMulticaster,默认的且在工厂中注册为单例的。

####### SimpleApplicationEventMulticaster中关于开启异步线程池,防止个别通知耗时太长,堵塞线程。

By default, all listeners are invoked in the calling thread. This allows the danger of a
rogue listener blocking the entire application, but adds minimal overhead.
Specify an alternative task executor to have listeners executed in different 
threads, for example from a thread pool

可以根据上面的方式,自定义实现applicationEventMulticaster的实现bean。实现方式如下:

@Configuration
public class AsyncEventConfig implements BeanFactoryAware {
    private BeanFactory beanFactory;

    @Bean(name = "applicationEventMulticaster")
    public ApplicationEventMulticaster simpleApplicationEventMulticaster() {
        SimpleApplicationEventMulticaster eventMulticaster
                = new SimpleApplicationEventMulticaster(beanFactory);

        eventMulticaster.setTaskExecutor(new SimpleAsyncTaskExecutor());
        return eventMulticaster;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }
}
ApplicationListener监听器都需要实现这个接口,其中有一个方法onApplicationEvent。
   void onApplicationEvent(E event)

当多播器调用的时候,会根据类型筛选,然后调用监听者的onApplicationEvent方法。