zoukankan      html  css  js  c++  java
  • Bean实例化(Spring源码阅读)-我们到底能走多远系列(33)

    我们到底能走多远系列(33)

    扯淡:

       各位:

          命运就算颠沛流离
         命运就算曲折离奇
         命运就算恐吓着你做人没趣味
         别流泪 心酸 更不应舍弃

         ...

    主题:

      Spring源码阅读还在继续,上篇文章初始化IoC容器:摸我

      事实上前面的IOC容器初始化只是建立了BeanDefinition数据映射,而依赖注入的过程是在向Ioc容器索要bean的时候发生的。

      getBean就是触发依赖注入的地方。

      1,下面是AbstractBeanFactory的getBean实现。根据scop进行分支处理,比较清晰

      注意:关于spring中的 bean的scop属性,有两个很常用:singleton和prototype

      singleton:这是Spring容器默认的作用域,使用singleton作用域生成的是单实例,在整个Bean容器中仅保留一个实例对象供所有调用者共享引用。单例模式对于那些无会话状态的Bean(如辅助工具类、DAO组件、业务逻辑组件等)是最理想的选择。

      prototype: 原型模式,这是多实例作用域,针对每次不同的请求,Bean容器均会生成一个全新的Bean实例以供调用者使用。

        public Object getBean(String name) throws BeansException {
            // 最终调用doGetBean方法
            return doGetBean(name, null, null, false);
        }
    
        public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
            return doGetBean(name, requiredType, null, false);
        }
    
        public Object getBean(String name, Object... args) throws BeansException {
            return doGetBean(name, null, args, false);
        }
    
        public <T> T getBean(String name, Class<T> requiredType, Object... args) throws BeansException {
            return doGetBean(name, requiredType, args, false);
        }
    View Code
        protected <T> T doGetBean(
                final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
                throws BeansException {
            final String beanName = transformedBeanName(name);
            Object bean;
            // Eagerly check singleton cache for manually registered singletons.
            // 从已经建立的实例bean里找
            Object sharedInstance = getSingleton(beanName);
            if (sharedInstance != null && args == null) {
                if (logger.isDebugEnabled()) {
                    if (isSingletonCurrentlyInCreation(beanName)) {
                        logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                                "' that is not fully initialized yet - a consequence of a circular reference");
                    }
                    else {
                        logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
                    }
                }
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
            }
            else {
                // 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);
                    }
                }
                if (!typeCheckOnly) {
                    markBeanAsCreated(beanName);
                }
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);
                // Guarantee initialization of beans that the current bean depends on.
                // 取得本bean的依赖bean组
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    // 循环调用getBean方法,递归实现本bean的全部依赖
                    for (String dependsOnBean : dependsOn) {
                        getBean(dependsOnBean);
                        registerDependentBean(dependsOnBean, beanName);
                    }
                }
                // Create bean instance.
                // Singleton 情况
                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);
                }
                // Prototype 情况
                else if (mbd.isPrototype()) {
                    // It's a prototype -> create a new instance.
                    Object prototypeInstance = null;
                    try {
                        beforePrototypeCreation(beanName);
                        // 最终大家都调这个方法来实例化Bean
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {
                        afterPrototypeCreation(beanName);
                    }
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }
                else {
                    // 其他scop情况
                    String scopeName = mbd.getScope();
                    final Scope scope = this.scopes.get(scopeName);
                    if (scope == null) {
                        throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
                    }
                    try {
                        Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
                            public Object getObject() throws BeansException {
                                beforePrototypeCreation(beanName);
                                try {
                                    return createBean(beanName, mbd, args);
                                }
                                finally {
                                    afterPrototypeCreation(beanName);
                                }
                            }
                        });
                        bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    }
                    catch (IllegalStateException ex) {
                        throw new BeanCreationException(beanName,
                                "Scope '" + scopeName + "' is not active for the current thread; " +
                                "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                                ex);
                    }
                }
            }

     

    2,上面代码会调用到AbstractAutowireCapableBeanFactory 的 createBean方法,这个方法中调用了内部的doCreateBean方法,createBean方法

        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);
            }
                    // 调用内部方法创建Bean
            Object beanInstance = doCreateBean(beanName, mbd, args);
            if (logger.isDebugEnabled()) {
                logger.debug("Finished creating instance of bean '" + beanName + "'");
            }
            return beanInstance;
        }
    View Code

    doCreateBean方法

    里面也就是调用createBeanInstance创建bean的方法真正出来一个bean后,在调用populateBean方法(链接)来初始化这个bean

        protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
            // Instantiate the bean.
            BeanWrapper instanceWrapper = null;
            if (mbd.isSingleton()) {
                instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
            }
            if (instanceWrapper == null) {
                // 创建bean的方法
                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() {
                    public Object getObject() throws BeansException {
                        return getEarlyBeanReference(beanName, mbd, bean);
                    }
                });
            }
    
            // Initialize the bean instance.
            Object exposedObject = bean;
            try {
                // 初始化创建出来的bean
                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);
                }
            }
    
            if (earlySingletonExposure) {
                Object earlySingletonReference = getSingleton(beanName, false);
                if (earlySingletonReference != null) {
                    if (exposedObject == bean) {
                        exposedObject = earlySingletonReference;
                    }
                    else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                        String[] dependentBeans = getDependentBeans(beanName);
                        Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
                        for (String dependentBean : dependentBeans) {
                            if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                                actualDependentBeans.add(dependentBean);
                            }
                        }
                        if (!actualDependentBeans.isEmpty()) {
                            throw new BeanCurrentlyInCreationException(beanName,
                                    "Bean with name '" + beanName + "' has been injected into other beans [" +
                                    StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                                    "] in its raw version as part of a circular reference, but has eventually been " +
                                    "wrapped. This means that said other beans do not use the final version of the " +
                                    "bean. This is often the result of over-eager type matching - consider using " +
                                    "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                        }
                    }
                }
            }
            // Register bean as disposable.
            try {
                registerDisposableBeanIfNecessary(beanName, bean, mbd);
            }
            catch (BeanDefinitionValidationException ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
            }
            return exposedObject;
        }
    View Code

    如此,我们先看createBeanInstance这个创建bean的方法是如何完成的。

    注意:在spring中有三种实例化bean的方式:

      一、使用构造器实例化,默认

    <bean id="personService" class="cn.mytest.service.impl.PersonServiceBean"></bean> 

      二、使用静态工厂方法实例化

    <bean id="personService1" class="cn.mytest.service.impl.PersonServiceFactory" factory-method="createPersonServiceBean"></bean>

      三、使用实例化工厂方法实例化

    <bean id="personServiceFactory" class="cn.mytest.service.impl.PersonServiceFactory"></bean>  
    <bean id="personService2" factory-bean="personServiceFactory" factory-method="createPersonServiceBean1"></bean>  

    这在createBeanInstance中有体现:

        protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
            // Make sure bean class is actually resolved at this point.
            Class beanClass = resolveBeanClass(mbd, beanName);
            if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
            }
            // 工厂方法实例化
            if (mbd.getFactoryMethodName() != null)  {
                return instantiateUsingFactoryMethod(beanName, mbd, args);
            }
            // Shortcut when re-creating the same bean...
            boolean resolved = false;
            boolean autowireNecessary = false;
            if (args == null) {
                synchronized (mbd.constructorArgumentLock) {
                    if (mbd.resolvedConstructorOrFactoryMethod != null) {
                        resolved = true;
                        autowireNecessary = mbd.constructorArgumentsResolved;
                    }
                }
            }
            if (resolved) {
                if (autowireNecessary) {
                    return autowireConstructor(beanName, mbd, null, null);
                }
                else {
                    return instantiateBean(beanName, mbd);
                }
            }
            // Need to determine the constructor...
            // 构造函数实例化
            Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
            if (ctors != null ||
                    mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
                    mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
                return autowireConstructor(beanName, mbd, ctors, args);
            }
            // No special handling: simply use no-arg constructor.
            return instantiateBean(beanName, mbd);
        }

    就直接看下简单常用的instantiateBean方法:

        protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
            try {
                Object beanInstance;
                final BeanFactory parent = this;
                if (System.getSecurityManager() != null) {
                    beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
                        public Object run() {
                            return getInstantiationStrategy().instantiate(mbd, beanName, parent);
                        }
                    }, getAccessControlContext());
                }
                else {
                    // spring默认的实例化策略是使用CGLIB来实例化bean
                    beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
                }
                BeanWrapper bw = new BeanWrapperImpl(beanInstance);
                initBeanWrapper(bw);
                return bw;
            }
            catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
            }
        }

    CGLIBcglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现。

    使用CGLB实例化代码:

        public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {
            // Don't override the class with CGLIB if no overrides.
            if (beanDefinition.getMethodOverrides().isEmpty()) {
                Constructor<?> constructorToUse;
                synchronized (beanDefinition.constructorArgumentLock) {
                    constructorToUse = (Constructor<?>) beanDefinition.resolvedConstructorOrFactoryMethod;
                    if (constructorToUse == null) {
                        final Class clazz = beanDefinition.getBeanClass();
                        if (clazz.isInterface()) {
                            throw new BeanInstantiationException(clazz, "Specified class is an interface");
                        }
                        try {
                            if (System.getSecurityManager() != null) {
                                constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor>() {
                                    public Constructor run() throws Exception {
                                        return clazz.getDeclaredConstructor((Class[]) null);
                                    }
                                });
                            }
                            else {
                                constructorToUse =    clazz.getDeclaredConstructor((Class[]) null);
                            }
                            beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse;
                        }
                        catch (Exception ex) {
                            throw new BeanInstantiationException(clazz, "No default constructor found", ex);
                        }
                    }
                }
                return BeanUtils.instantiateClass(constructorToUse);
            }
            else {
                // Must generate CGLIB subclass.
                // 使用CGLIB实现实例化bean
                return instantiateWithMethodInjection(beanDefinition, beanName, owner);
            }
        }
        
        protected Object instantiateWithMethodInjection(
                RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {
    
            // Must generate CGLIB subclass.
            return new CglibSubclassCreator(beanDefinition, owner).instantiate(null, null);
        }
        
            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);
            }
    View Code

    到这里,创建bean的过程是完成了,关于bean的一些初始化的操作及调用populateBean方法下次再研究吧。

    事实上spring提供了jvm的反射实现的代理,和cglib实现的代理,来实例化java对象。

    下面就稍微学习下这两种不同的代理方式:

    代理模式也是常用的设计模式,分为两种:静态代理和动态代理

    静态代理

    /**
     * 定义一个账户接口
     * 
     * @author Administrator
     */
    public interface Count {
        // 查看账户方法
        public void queryCount();
        // 修改账户方法
        public void updateCount();
    }
    public class CountImpl implements Count {
    
        @Override  
        public void queryCount() {  
            System.out.println("查看账户方法...");  
        }  
        @Override  
        public void updateCount() {  
            System.out.println("修改账户方法...");  
        }  
    }
    /** 
     * 这是一个代理类(增强CountImpl实现类) 
     *  
     * @author Administrator 
     *  
     */  
    public class CountProxy implements Count {  
        private CountImpl countImpl;  
      
        /** 
         * 覆盖默认构造器 
         *  
         * @param countImpl 
         */  
        public CountProxy(CountImpl countImpl) {  
            this.countImpl = countImpl;  
        }  
        @Override  
        public void queryCount() {  
            System.out.println("事务处理之前");  
            // 调用委托类的方法;  
            countImpl.queryCount();  
            System.out.println("事务处理之后");  
        }  
        @Override  
        public void updateCount() {  
            System.out.println("事务处理之前");  
            // 调用委托类的方法;  
            countImpl.updateCount();  
            System.out.println("事务处理之后");  
        }  
    }  
    public class TestCount {
        public static void main(String[] args) {
            CountImpl countImpl = new CountImpl();  
            CountProxy countProxy = new CountProxy(countImpl);  
            countProxy.updateCount();  
            countProxy.queryCount();  
        }
    }

    动态代理

    public interface BookFacade {
        public void addBook();  
    }
    public class BookFacadeImpl implements BookFacade {
        @Override
        public void addBook() {
            System.out.println("增加图书方法。。。");  
        }
    }
    public class BookFacadeProxy implements InvocationHandler{
    
        private Object target;
    
        /**
         * 绑定委托对象并返回一个代理类
         * 
         * @param target
         * @return
         */
        public Object bind(Object target) {
            this.target = target;
            // 取得代理对象
            // 要绑定接口(这是一个缺陷,cglib弥补了这一缺陷)
            
            return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); 
        }
    
        @Override
        /** 
         * 调用方法 
         * Object proxy:指被代理的对象
         * Method method:要调用的方法 
         * Object[] args:方法调用时所需要的参数 
         */
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Object result = null;
            System.out.println("事物开始");
            // 执行方法
            result = method.invoke(target, args);
            System.out.println("事物结束");
            return result;
        }
    }
    public class TestProxy {
        public static void main(String[] args) {  
            BookFacadeProxy proxy = new BookFacadeProxy();  
            BookFacade bookProxy = (BookFacade) proxy.bind(new BookFacadeImpl());  
            bookProxy.addBook();  
        } 
    }

    以上的代理方式需要有接口的类来可以,所以使用cglib弥补了这一缺点,这也是不同之处:

    /** 
     * 这个是没有实现接口的实现类 
     */
    public class BookFacadeCglibImpl {
        public void addBook() {  
            System.out.println("增加图书的普通方法...");  
        }
    }
    public class BookFacadeCglib implements MethodInterceptor{
        private Object target;  
        
        /** 
         * 创建代理对象 
         *  
         * @param target 
         * @return 
         */  
        public Object getInstance(Object target) {  
            this.target = target;  
            Enhancer enhancer = new Enhancer();  
            enhancer.setSuperclass(this.target.getClass());  
            // 回调方法  
            enhancer.setCallback(this);  
            // 创建代理对象  
            return enhancer.create();  
        }  
      
        @Override  
        // 回调方法  
        public Object intercept(Object obj, Method method, Object[] args,  
                MethodProxy proxy) throws Throwable {  
            System.out.println("事物开始");  
            proxy.invokeSuper(obj, args);  
            System.out.println("事物结束");  
            return null;  
        }  
    }
    public class TestCglib {
        public static void main(String[] args) {  
            BookFacadeCglib cglib=new BookFacadeCglib();  
            BookFacadeCglibImpl bookCglib=(BookFacadeCglibImpl)cglib.getInstance(new BookFacadeCglibImpl());  
            bookCglib.addBook();
        } 
    }

    总结:

    学习是没有止境的,当我们学得更多的时候,我们就会发现自己不知道的东西越来越多。

    设计模式很难学,今天看一遍明天就忘了,实际编码能想起来更难~

    让我们继续前行

    ----------------------------------------------------------------------

    努力不一定成功,但不努力肯定不会成功。
    共勉。

  • 相关阅读:
    Below is a nice utility class for Enums
    ASP.NET页面与IIS底层交互和工作原理详解
    深入理解 __doPostBack
    DataList控件显示图片要的是效果
    Below is a nice utility class for Enums
    ExtensionMethods Class
    showModalDialog中打开新页面Session丢失
    Delegate,Action,Func,匿名方法,匿名委托,事件
    异步编程:IAsyncResult异步编程模型 (APM)
    C#线程系列讲座(1):BeginInvoke和EndInvoke方法
  • 原文地址:https://www.cnblogs.com/killbug/p/3283382.html
Copyright © 2011-2022 走看看