(转)
分析Spring源代码之,DI的实现
2012/1/3 by tony
接着上次的讲,以下这个sample
- package com.hyron.tony;
- import org.springframework.beans.factory.BeanFactory;
- import org.springframework.beans.factory.xml.XmlBeanFactory;
- import org.springframework.core.io.ClassPathResource;
- public class Test {
- public static void main(String[] args)throws Exception {
- BeanFactory factory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
- GreetingService greetingService = (GreetingService)factory.getBean("greetingService");
- greetingService.sayGreeting();
- }
- }
Bean的实时启动,就是以下这行代码:
- (GreetingService)factory.getBean("greetingService");
他的执行树如下:
Factory.getBean
-- XmlBeanFactory
--AbstractAutowireCapableBeanFactory
-- AbstractBeanFactory 在其中找到如下方法
- //---------------------------------------------------------------------
- // Implementation of BeanFactory interface
- //---------------------------------------------------------------------
- public Object getBean(String name) throws BeansException {
- return doGetBean(name, null, null, false);
- }
doGetBean的方法声明:
- /**
- * Return an instance, which may be shared or independent, of the specified bean.
- * @param name the name of the bean to retrieve
- * @param requiredType the required type of the bean to retrieve
- * @param args arguments to use if creating a prototype using explicit arguments to a
- * static factory method. It is invalid to use a non-null args value in any other case.
- * @param typeCheckOnly whether the instance is obtained for a type check,
- * not for actual use
- * @return an instance of the bean
- * @throws BeansException if the bean could not be created
- */
- @SuppressWarnings("unchecked")
- protected <T> T doGetBean(
- final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
- throws BeansException {
- }
我真觉得有时候研究人家代码真不如看人家注释,特别是很好的开源架构,代码是好得很
doGetBean方法中比较有意思的代码如下:
//将beanName前面可能的&符号滤掉
- final String beanName = transformedBeanName(name);
//得到已经登记过的单例Object,而不是再次生成它
- Object sharedInstance = getSingleton(beanName);
它的具体代码如下:
- /**
- * Return the (raw) singleton object registered under the given name.
- * <p>Checks already instantiated singletons and also allows for an early
- * reference to a currently created singleton (resolving a circular reference).
- * @param beanName the name of the bean to look for
- * @param allowEarlyReference whether early references should be created or not
- * @return the registered singleton object, or <code>null</code> if none found
- */
- protected Object getSingleton(String beanName, boolean allowEarlyReference) {
- Object singletonObject = this.singletonObjects.get(beanName);
- if (singletonObject == null) {
- 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);
- }
- }
- }
- }
- return (singletonObject != NULL_OBJECT ? singletonObject : null);
- }
其中有一点比较有意思,就是singletonFactories是在哪里塞入的
以下:
- /**
- * Add the given singleton factory for building the specified singleton
- * if necessary.
- * <p>To be called for eager registration of singletons, e.g. to be able to
- * resolve circular references.
- * @param beanName the name of the bean
- * @param singletonFactory the factory for the singleton object
- */
- protected void addSingletonFactory(String beanName, ObjectFactory singletonFactory) {
- Assert.notNull(singletonFactory, "Singleton factory must not be null");
- synchronized (this.singletonObjects) {
- if (!this.singletonObjects.containsKey(beanName)) {
- this.singletonFactories.put(beanName, singletonFactory);
- this.earlySingletonObjects.remove(beanName);
- this.registeredSingletons.add(beanName);
- }
- }
- }
这个方法被执行与createBean
createBean的执行其实是在doGetBean方法内本身
接下来从一个BeanFactory中获得对象的instance
- /**
- * Get the object for the given bean instance, either the bean
- * instance itself or its created object in case of a FactoryBean.
- * @param beanInstance the shared bean instance
- * @param name name that may include factory dereference prefix
- * @param beanName the canonical bean name
- * @param mbd the merged bean definition
- * @return the object to expose for the bean
- */
- protected Object getObjectForBeanInstance(
- Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
- // Don't let calling code try to dereference the factory if the bean isn't a factory.
- if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
- throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
- }
- // Now we have the bean instance, which may be a normal bean or a FactoryBean.
- // If it's a FactoryBean, we use it to create a bean instance, unless the
- // caller actually wants a reference to the factory.
- if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
- return beanInstance;
- }
- Object object = null;
- if (mbd == null) {
- object = getCachedObjectForFactoryBean(beanName);
- }
- if (object == null) {
- // Return bean instance from factory.
- FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
- // Caches object obtained from FactoryBean if it is a singleton.
- if (mbd == null && containsBeanDefinition(beanName)) {
- mbd = getMergedLocalBeanDefinition(beanName);
- }
- boolean synthetic = (mbd != null && mbd.isSynthetic());
- object = getObjectFromFactoryBean(factory, beanName, !synthetic);
- }
- return object;
- }
否则的话,失败的话,则从BeanFacory中动态生成对象实例
- // Fail if we're already creating this bean instance:
- // We're assumably within a circular reference.
- if (isPrototypeCurrentlyInCreation(beanName)) {
- throw new BeanCurrentlyInCreationException(beanName);
- }
- // Check if bean definition exists in this factory.
- BeanFactory parentBeanFactory = getParentBeanFactory();
- if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
- // Not found -> check parent.
- String nameToLookup = originalBeanName(name);
- if (args != null) {
- // Delegation to parent with explicit args.
- return (T) parentBeanFactory.getBean(nameToLookup, args);
- }
- else {
- // No args -> delegate to standard getBean method.
- return parentBeanFactory.getBean(nameToLookup, requiredType);
- }
- }
以上这段代码真的很让人费解,什么是BeanFactory,什么是FactoryBean
接下来,如果在失败,就直接createBean
- // Create bean instance.
- if (mbd.isSingleton()) {
- sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
- public Object getObject() throws BeansException {
- try {
- return createBean(beanName, mbd, args);
- }
- catch (BeansException ex) {
- // Explicitly remove instance from singleton cache: It might have been put there
- // eagerly by the creation process, to allow for circular reference resolution.
- // Also remove any beans that received a temporary reference to the bean.
- destroySingleton(beanName);
- throw ex;
- }
- }
- });
- bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
- }
其中createBean是写在父类中的抽象类 AbstractAutowireCapableBeanFactory中
- /**
- * Central method of this class: creates a bean instance,
- * populates the bean instance, applies post-processors, etc.
- * @see #doCreateBean
- */
- @Override
- protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
- throws BeanCreationException {
- if (logger.isDebugEnabled()) {
- logger.debug("Creating instance of bean '" + beanName + "'");
- }
- // Make sure bean class is actually resolved at this point.
- resolveBeanClass(mbd, beanName);
- // Prepare method overrides.
- try {
- mbd.prepareMethodOverrides();
- }
- catch (BeanDefinitionValidationException ex) {
- throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
- beanName, "Validation of method overrides failed", ex);
- }
- try {
- // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
- Object bean = resolveBeforeInstantiation(beanName, mbd);
- if (bean != null) {
- return bean;
- }
- }
- catch (Throwable ex) {
- throw new BeanCreationException(mbd.getResourceDescription(), beanName,
- "BeanPostProcessor before instantiation of bean failed", ex);
- }
- Object beanInstance = doCreateBean(beanName, mbd, args);
- if (logger.isDebugEnabled()) {
- logger.debug("Finished creating instance of bean '" + beanName + "'");
- }
- return beanInstance;
- }
其中真正反射生成对象instance的是
- protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
这个方法分成两部分:
第一,生成对象instance的Wapper,用到了包装者模式
- if (instanceWrapper == null) {
- instanceWrapper = createBeanInstance(beanName, mbd, args);
- }
第二,实例化对象instance
- // 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);
- }
- }
其中createBeanInstance中最简单的生成期是
- // No special handling: simply use no-arg constructor.
- return instantiateBean(beanName, mbd);
它的核心代码:
- if (System.getSecurityManager() != null) {
- beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- return getInstantiationStrategy().instantiate(mbd, beanName, parent);
- }
- }, getAccessControlContext());
- }
- else {
- beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
- }
这里使用了策略模式,将实际的算法放到策略接口中去
一般最简单的实现的策略模式就是:
- /**
- * Default object instantiation strategy for use in BeanFactories.
- * Uses CGLIB to generate subclasses dynamically if methods need to be
- * overridden by the container, to implement Method Injection.
- *
- * <p>Using Method Injection features requires CGLIB on the classpath.
- * However, the core IoC container will still run without CGLIB being available.
- *
- * @author Rod Johnson
- * @author Juergen Hoeller
- * @since 1.1
- */
- public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationStrategy {
- /**
- * Create a new instance of a dynamically generated subclasses implementing the
- * required lookups.
- * @param ctor constructor to use. If this is <code>null</code>, use the
- * no-arg constructor (no parameterization, or Setter Injection)
- * @param args arguments to use for the constructor.
- * Ignored if the ctor parameter is <code>null</code>.
- * @return new instance of the dynamically generated class
- */
- public Object instantiate(Constructor ctor, Object[] args) {
- Enhancer enhancer = new Enhancer();
- enhancer.setSuperclass(this.beanDefinition.getBeanClass());
- enhancer.setCallbackFilter(new CallbackFilterImpl());
- enhancer.setCallbacks(new Callback[] {
- NoOp.INSTANCE,
- new LookupOverrideMethodInterceptor(),
- new ReplaceOverrideMethodInterceptor()
- });
- return (ctor == null) ?
- enhancer.create() :
- enhancer.create(ctor.getParameterTypes(), args);
- }
真正最终的对象生成器是
- net.sf.cglib.proxy.Enhancer;
spring没有用原生态的代理反射,而是用这个开源jar包来实现了动态生成
最后spring对对象的实例化,和参数的注入,是以下代码:
- /**
- * Populate the bean instance in the given BeanWrapper with the property values
- * from the bean definition.
- * @param beanName the name of the bean
- * @param mbd the bean definition for the bean
- * @param bw BeanWrapper with bean instance
- */
- protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) {
- PropertyValues pvs = mbd.getPropertyValues();
- if (bw == null) {
- if (!pvs.isEmpty()) {
- throw new BeanCreationException(
- mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
- }
- else {
- // Skip property population phase for null instance.
- return;
- }
- }
- // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
- // state of the bean before properties are set. This can be used, for example,
- // to support styles of field injection.
- boolean continueWithPropertyPopulation = true;
- if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
- for (BeanPostProcessor bp : getBeanPostProcessors()) {
- if (bp instanceof InstantiationAwareBeanPostProcessor) {
- InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
- if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
- continueWithPropertyPopulation = false;
- break;
- }
- }
- }
- }
- if (!continueWithPropertyPopulation) {
- return;
- }
- 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;
- }
- boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
- boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
- if (hasInstAwareBpps || needsDepCheck) {
- PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw);
- if (hasInstAwareBpps) {
- for (BeanPostProcessor bp : getBeanPostProcessors()) {
- if (bp instanceof InstantiationAwareBeanPostProcessor) {
- InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
- pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
- if (pvs == null) {
- return;
- }
- }
- }
- }
- if (needsDepCheck) {
- checkDependencies(beanName, mbd, filteredPds, pvs);
- }
- }
- applyPropertyValues(beanName, mbd, bw, pvs);
- }
我真不知道这些代码是怎么写出来的。
怎么能这么牛,有时候看到这些浩如烟海的牛逼的代码,真是觉得自己和人家比起来,技术的道路算是到头了。
这些人真是他妈的天才。
附:cglib的简单介绍:
http://java.csecs.com/posts/list/1633.html
http://www.blogjava.net/stone2083/archive/2008/03/16/186615.html
http://www.blogjava.net/georgehill/archive/2005/05/24/5126.html