在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 問答/Java/ 關于抽象類的問題

關于抽象類的問題

看Spring源碼想到的一個問題

/*
 * Copyright 2002-2004 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.beans.factory.support;

import java.beans.PropertyEditor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanIsNotAFactoryException;
import org.springframework.beans.factory.BeanNotOfRequiredTypeException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.FactoryBeanCircularReferenceException;
import org.springframework.beans.factory.HierarchicalBeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;

/**
 * Abstract superclass for BeanFactory implementations.
 * Implements the ConfigurableBeanFactory SPI interface.
 *
 * <p>This class provides singleton/prototype determination, singleton cache,
 * aliases, FactoryBean handling, and bean definition merging for child bean
 * definitions. It also allows for management of a bean factory hierarchy,
 * implementing the HierarchicalBeanFactory interface.
 *
 * <p>The main template methods to be implemented by subclasses are
 * getBeanDefinition and createBean, retrieving a bean definition for
 * a given bean name respectively creating a bean instance for a given
 * bean definition.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @since 15 April 2001
 * @version $Id: AbstractBeanFactory.java,v 1.51 2004/03/23 20:16:59 jhoeller Exp $
 * @see #getBeanDefinition
 * @see #createBean
 */
public abstract class AbstractBeanFactory implements ConfigurableBeanFactory, HierarchicalBeanFactory {

    /**
     * Used to dereference a FactoryBean and distinguish it from
     * beans <i>created</i> by the factory. For example,
     * if the bean named <code>myEjb</code> is a factory, getting
     * <code>&myEjb</code> will return the factory, not the instance
     * returned by the factory.
     */
    public static final String FACTORY_BEAN_PREFIX = "&";


    /** Logger available to subclasses */
    protected final Log logger = LogFactory.getLog(getClass());

    /** Parent bean factory, for bean inheritance support */
    private BeanFactory parentBeanFactory;

    /** Custom PropertyEditors to apply to the beans of this factory */
    private Map customEditors = new HashMap();

    /** Dependency types to ignore on dependency check and autowire */
    private final Set ignoreDependencyTypes = new HashSet();

    /** BeanPostProcessors to apply in createBean */
    private final List beanPostProcessors = new ArrayList();

    /** Map from alias to canonical bean name */
    private final Map aliasMap = Collections.synchronizedMap(new HashMap());

    /** Cache of singletons: bean name --> bean instance */
    private final Map singletonCache = Collections.synchronizedMap(new HashMap());


    /**
     * Create a new AbstractBeanFactory.
     */
    public AbstractBeanFactory() {
        ignoreDependencyType(BeanFactory.class);
    }

    /**
     * Create a new AbstractBeanFactory with the given parent.
     * @param parentBeanFactory parent bean factory, or null if none
     * @see #getBean
     */
    public AbstractBeanFactory(BeanFactory parentBeanFactory) {
        this();
        this.parentBeanFactory = parentBeanFactory;
    }


    //---------------------------------------------------------------------
    // Implementation of BeanFactory
    //---------------------------------------------------------------------

    /**
     * Return the bean with the given name,
     * checking the parent bean factory if not found.
     * @param name name of the bean to retrieve
     */
    public Object getBean(String name) throws BeansException {
        String beanName = transformedBeanName(name);
        // eagerly check singleton cache for manually registered singletons
        Object sharedInstance = this.singletonCache.get(beanName);
        if (sharedInstance != null) {
            if (logger.isDebugEnabled()) {
                logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
            }
            return getObjectForSharedInstance(name, sharedInstance);
        }
        else {
            // check if bean definition exists
            RootBeanDefinition mergedBeanDefinition = null;
            try {
                mergedBeanDefinition = getMergedBeanDefinition(beanName, false);
            }
            catch (NoSuchBeanDefinitionException ex) {
                // not found -> check parent
                if (this.parentBeanFactory != null) {
                    return this.parentBeanFactory.getBean(name);
                }
                throw ex;
            }
            // create bean instance
            if (mergedBeanDefinition.isSingleton()) {
                synchronized (this.singletonCache) {
                    // re-check singleton cache within synchronized block
                    sharedInstance = this.singletonCache.get(beanName);
                    if (sharedInstance == null) {
                        logger.info("Creating shared instance of singleton bean '" + beanName + "'");
                        sharedInstance = createBean(beanName, mergedBeanDefinition);
                        addSingleton(beanName, sharedInstance);
                    }
                }
                return getObjectForSharedInstance(name, sharedInstance);
            }
            else {
                return createBean(name, mergedBeanDefinition);
            }
        }
    }

    public Object getBean(String name, Class requiredType) throws BeansException {
        Object bean = getBean(name);
        if (!requiredType.isAssignableFrom(bean.getClass())) {
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean);
        }
        return bean;
    }

    public boolean containsBean(String name) {
        String beanName = transformedBeanName(name);
        if (this.singletonCache.containsKey(beanName)) {
            return true;
        }
        if (containsBeanDefinition(beanName)) {
            return true;
        }
        else {
            // not found -> check parent
            if (this.parentBeanFactory != null) {
                return this.parentBeanFactory.containsBean(beanName);
            }
            else {
                return false;
            }
        }
    }

    public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
        String beanName = transformedBeanName(name);
        try {
            Class beanClass = null;
            boolean singleton = true;
            Object beanInstance = this.singletonCache.get(beanName);
            if (beanInstance != null) {
                beanClass = beanInstance.getClass();
                singleton = true;
            }
            else {
                RootBeanDefinition bd = getMergedBeanDefinition(beanName, false);
                beanClass = bd.getBeanClass();
                singleton = bd.isSingleton();
            }
            // in case of FactoryBean, return singleton status of created object if not a dereference
            if (FactoryBean.class.isAssignableFrom(beanClass) && !isFactoryDereference(name)) {
                FactoryBean factoryBean = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);
                return factoryBean.isSingleton();
            }
            else {
                return singleton;
            }
        }
        catch (NoSuchBeanDefinitionException ex) {
            // not found -> check parent
            if (this.parentBeanFactory != null) {
                return this.parentBeanFactory.isSingleton(beanName);
            }
            throw ex;
        }
    }

    public String[] getAliases(String name) throws NoSuchBeanDefinitionException {
        String beanName = transformedBeanName(name);
        // check if bean actually exists in this bean factory
        if (this.singletonCache.containsKey(beanName) || containsBeanDefinition(beanName)) {
            // if found, gather aliases
            List aliases = new ArrayList();
            for (Iterator it = this.aliasMap.entrySet().iterator(); it.hasNext();) {
                Map.Entry entry = (Map.Entry) it.next();
                if (entry.getValue().equals(beanName)) {
                    aliases.add(entry.getKey());
                }
            }
            return (String[]) aliases.toArray(new String[aliases.size()]);
        }
        else {
            // not found -> check parent
            if (this.parentBeanFactory != null) {
                return this.parentBeanFactory.getAliases(beanName);
            }
            throw new NoSuchBeanDefinitionException(beanName, toString());
        }
    }


    //---------------------------------------------------------------------
    // Implementation of HierarchicalBeanFactory
    //---------------------------------------------------------------------

    public BeanFactory getParentBeanFactory() {
        return parentBeanFactory;
    }


    //---------------------------------------------------------------------
    // Implementation of ConfigurableBeanFactory
    //---------------------------------------------------------------------

    public void setParentBeanFactory(BeanFactory parentBeanFactory) {
        this.parentBeanFactory = parentBeanFactory;
    }

    public void registerCustomEditor(Class requiredType, PropertyEditor propertyEditor) {
        this.customEditors.put(requiredType, propertyEditor);
    }

    /**
     * Return the map of custom editors, with Classes as keys
     * and PropertyEditors as values.
     */
    public Map getCustomEditors() {
        return customEditors;
    }

    public void ignoreDependencyType(Class type) {
        this.ignoreDependencyTypes.add(type);
    }

    /**
     * Return the set of classes that will get ignored for autowiring.
     */
    public Set getIgnoredDependencyTypes() {
        return ignoreDependencyTypes;
    }

    public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
        this.beanPostProcessors.add(beanPostProcessor);
    }

    /**
     * Return the list of BeanPostProcessors that will get applied
     * to beans created with this factory.
     */
    public List getBeanPostProcessors() {
        return beanPostProcessors;
    }

    public void registerAlias(String beanName, String alias) throws BeanDefinitionStoreException {
        logger.debug("Registering alias '" + alias + "' for bean with name '" + beanName + "'");
        synchronized (this.aliasMap) {
            Object registeredName = this.aliasMap.get(alias);
            if (registeredName != null) {
                throw new BeanDefinitionStoreException("Cannot register alias '" + alias + "' for bean name '" + beanName +
                                                                                             "': it's already registered for bean name '" + registeredName + "'");
            }
            this.aliasMap.put(alias, beanName);
        }
    }

    public void registerSingleton(String beanName, Object singletonObject) throws BeanDefinitionStoreException {
        synchronized (this.singletonCache) {
            Object oldObject = this.singletonCache.get(beanName);
            if (oldObject != null) {
                throw new BeanDefinitionStoreException("Could not register object [" + singletonObject +
                                                                                             "] under bean name '" + beanName + "': there's already object [" +
                                                                                             oldObject + " bound");
            }
            addSingleton(beanName, singletonObject);
        }
    }

    /**
     * Add the given singleton object to the singleton cache of this factory.
     * <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 singletonObject the singleton object
     */
    protected void addSingleton(String beanName, Object singletonObject) {
        this.singletonCache.put(beanName, singletonObject);
    }

    public void destroySingletons() {
        if (logger.isInfoEnabled()) {
            logger.info("Destroying singletons in factory {" + this + "}");
        }
        synchronized (this.singletonCache) {
            Set singletonCacheKeys = new HashSet(this.singletonCache.keySet());
            for (Iterator it = singletonCacheKeys.iterator(); it.hasNext();) {
                destroySingleton((String) it.next());
            }
        }
    }

    /**
     * Destroy the given bean. Delegates to destroyBean if a corresponding
     * singleton instance is found.
     * @param beanName name of the bean
     * @see #destroyBean
     */
    protected void destroySingleton(String beanName) {
        Object singletonInstance = this.singletonCache.remove(beanName);
        if (singletonInstance != null) {
            destroyBean(beanName, singletonInstance);
        }
    }


    //---------------------------------------------------------------------
    // Implementation methods
    //---------------------------------------------------------------------

    /**
     * Return the bean name, stripping out the factory dereference prefix if necessary,
     * and resolving aliases to canonical names.
     */
    protected String transformedBeanName(String name) throws NoSuchBeanDefinitionException {
        if (name == null) {
            throw new NoSuchBeanDefinitionException(name, "Cannot get bean with null name");
        }
        if (name.startsWith(FACTORY_BEAN_PREFIX)) {
            name = name.substring(FACTORY_BEAN_PREFIX.length());
        }
        // handle aliasing
        String canonicalName = (String) this.aliasMap.get(name);
        return canonicalName != null ? canonicalName : name;
    }

    /**
     * Return whether this name is a factory dereference
     * (beginning with the factory dereference prefix).
     */
    protected boolean isFactoryDereference(String name) {
        return name.startsWith(FACTORY_BEAN_PREFIX);
    }

    /**
     * Initialize the given BeanWrapper with the custom editors registered
     * with this factory.
     * @param bw the BeanWrapper to initialize
     */
    protected void initBeanWrapper(BeanWrapper bw) {
        for (Iterator it = this.customEditors.keySet().iterator(); it.hasNext();) {
            Class clazz = (Class) it.next();
            bw.registerCustomEditor(clazz, (PropertyEditor) this.customEditors.get(clazz));
        }
    }

    /**
     * Return the names of beans in the singleton cache that match the given
     * object type (including subclasses). Will <i>not</i> consider FactoryBeans
     * as the type of their created objects is not known before instantiation.
     * <p>Does not consider any hierarchy this factory may participate in.
     * @param type class or interface to match, or null for all bean names
     * @return the names of beans in the singleton cache that match the given
     * object type (including subclasses), or an empty array if none
     */
    public String[] getSingletonNames(Class type) {
        Set keys = this.singletonCache.keySet();
        Set matches = new HashSet();
        Iterator itr = keys.iterator();
        while (itr.hasNext()) {
            String name = (String) itr.next();
            Object singletonObject = this.singletonCache.get(name);
            if (type == null || type.isAssignableFrom(singletonObject.getClass())) {
                matches.add(name);
            }
        }
        return (String[]) matches.toArray(new String[matches.size()]);
    }

    /**
     * Get the object for the given shared bean, either the bean
     * instance itself or its created object in case of a FactoryBean.
     * @param name name that may include factory dereference prefix
     * @param beanInstance the shared bean instance
     * @return the singleton instance of the bean
     */
    protected Object getObjectForSharedInstance(String name, Object beanInstance) {
        String beanName = transformedBeanName(name);

        // Don't let calling code try to dereference the
        // bean factory if the bean isn't a factory
        if (isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
            throw new BeanIsNotAFactoryException(beanName, beanInstance);
        }

        // 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) {
            if (!isFactoryDereference(name)) {
                // return bean instance from factory
                FactoryBean factory = (FactoryBean) beanInstance;
                logger.debug("Bean with name '" + beanName + "' is a factory bean");
                try {
                    beanInstance = factory.getObject();
                }
                catch (BeansException ex) {
                    throw ex;
                }
                catch (Exception ex) {
                    throw new BeanCreationException("FactoryBean threw exception on object creation", ex);
                }
                if (beanInstance == null) {
                    throw new FactoryBeanCircularReferenceException(
                        "Factory bean '" + beanName + "' returned null object - " +
                        "possible cause: not fully initialized due to circular bean reference");
                }
            }
            else {
                // the user wants the factory itself
                logger.debug("Calling code asked for FactoryBean instance for name '" + beanName + "'");
            }
        }

        return beanInstance;
    }

    /**
     * Return a RootBeanDefinition, even by traversing parent if the parameter is a child definition.
     * Will ask the parent bean factory if not found in this instance.
     * @return a merged RootBeanDefinition with overridden properties
     */
    public RootBeanDefinition getMergedBeanDefinition(String beanName, boolean includingAncestors)
        throws BeansException {
        try {
            return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
        }
        catch (NoSuchBeanDefinitionException ex) {
            if (includingAncestors && getParentBeanFactory() instanceof AbstractAutowireCapableBeanFactory) {
                return ((AbstractAutowireCapableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(beanName, true);
            }
            else {
                throw ex;
            }
        }
    }

    /**
     * Return a RootBeanDefinition, even by traversing parent if the parameter is a child definition.
     * @return a merged RootBeanDefinition with overridden properties
     */
    protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd) {
        if (bd instanceof RootBeanDefinition) {
            return (RootBeanDefinition) bd;
        }
        else if (bd instanceof ChildBeanDefinition) {
            ChildBeanDefinition cbd = (ChildBeanDefinition) bd;
            // deep copy
            RootBeanDefinition rbd = new RootBeanDefinition(getMergedBeanDefinition(cbd.getParentName(), true));
            // override properties
            for (int i = 0; i < cbd.getPropertyValues().getPropertyValues().length; i++) {
                rbd.getPropertyValues().addPropertyValue(cbd.getPropertyValues().getPropertyValues()[i]);
            }
            // override settings
            rbd.setSingleton(cbd.isSingleton());
            rbd.setLazyInit(cbd.isLazyInit());
            rbd.setResourceDescription(cbd.getResourceDescription());
            return rbd;
        }
        else {
            throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
                                                                                         "Definition is neither a RootBeanDefinition nor a ChildBeanDefinition");
        }
    }

    //---------------------------------------------------------------------
    // Abstract methods to be implemented by concrete subclasses
    //---------------------------------------------------------------------

    /**
     * Check if this bean factory contains a bean definition with the given name.
     * Does not consider any hierarchy this factory may participate in.
     * Invoked by containsBean when no cached singleton instance is found.
     * @param beanName the name of the bean to look for
     * @return if this bean factory contains a bean definition with the given name
     * @see #containsBean
     */
    public abstract boolean containsBeanDefinition(String beanName);

    /**
     * Return the bean definition for the given bean name.
     * Subclasses should normally implement caching, as this method is invoked
     * by this class every time bean definition metadata is needed.
     * @param beanName name of the bean to find a definition for
     * @return the BeanDefinition for this prototype name. Must never return null.
     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
     * if the bean definition cannot be resolved
     * @throws BeansException in case of errors
     * @see RootBeanDefinition
     * @see ChildBeanDefinition
     */
    public abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;

    /**
     * Create a bean instance for the given bean definition.
     * The bean definition will already have been merged with the parent
     * definition in case of a child definition.
     * <p>All the other methods in this class invoke this method, although
     * beans may be cached after being instantiated by this method. All bean
     * instantiation within this class is performed by this method.
     * @param beanName name of the bean
     * @param mergedBeanDefinition the bean definition for the bean
     * @return a new instance of the bean
     * @throws BeansException in case of errors
     */
    protected abstract Object createBean(String beanName, RootBeanDefinition mergedBeanDefinition)
        throws BeansException;

    /**
     * Destroy the given bean. Must destroy beans that depend on the given
     * bean before the bean itself. Should not throw any exceptions.
     * @param beanName name of the bean
     * @param bean the bean instance to destroy
     */
    protected abstract void destroyBean(String beanName, Object bean);

}

這是Spring1.0的源碼,抽象類AbstractBeanFactory作為DefaultListableBeanFactory,XmlBeanFactory等的父類,在Spring factory的繼承關系中,XmlBeanFactory的父beanFactory,即都保存在AbstractBeanFactory的parentBeanFactory變量中,我們獲取parentBeanFactory可以通過AbstractBeanFactory的

public BeanFactory getParentBeanFactory() {
        return parentBeanFactory;
}

獲取即可,目前這些都沒有問題。

但是,突然想到,作為抽象類AbstractBeanFactory,其并不能實例化,那么問題來了,其抽象類中的成員變量(非類變量)的值是保存在哪里的?或者說抽象類在內存中中是怎樣存在的?

請教大家,謝謝。

回答
編輯回答
扯機薄

這個跟 Spring 沒有關系。

類,不占用任何空間,只是敘述了對象占用了怎樣的空間。 類是類型的意思,就像int也是類型。 int 并不占用空間,但是int aa 占用32 bytes內存空間,而 double f; f占64 bytes 空間,這些是編譯器預定義的類型。但是類(e.g. BaseClass)是我們自定義的類型,因此我們要寫代碼描述如何創(chuàng)建這個類型。BaseClass obj = new BaseClass();obj 才占用空間。

class ExtClass extends BaseClass {}; ExtClass ex = new ExtClass() 的 ex 才占用空間。 在給其分配內存的時候 首先分配 BaseClass 描述的成員變量的空間,然后再分配ExtClass中描述的成員變量占用的空間。

obj -> +------------------+
       | BaseClass的props |
       +------------------+
       |      其他        |
       +------------------+

ext -> +------------------+
       | BaseClass的props |
       +------------------+
       |      其他        |
       +------------------+
       | ExtClass的props  |
       +------------------+
       |      其他        |
       +------------------+

其他 包括一下存儲類中方法、static等東西的“指針”等。。。

抽象類不能實例化,但其子類可以實例化,子類實例化的時候顯然要要先給其父類定義的成員變量分配空間。

因此,對于static 方法,只能訪問static 變量,因為這個時候其他成員變量還沒有分配空間。static成員實在程序初始化的時候分配的空間,所有的對象共享,所以即使沒有創(chuàng)建對象,這些成員也是在內存中存在的,所以這些值可以通過類名訪問。但是其他方法,必須通過這個類的對象訪問,也就是必須通過一個已經實例化的對象進行訪問,這些成員變量有了內存空間,就可以訪問了。

所以你調用了非static方法,就必然說明在某個地方實例化了這個類或是其子類,通過這個對象對這個函數進行調用,這樣基類所定義的屬性也有了分配空間。

抽象類不能實例化主要是因為其中的一些方法沒有實現,等待其子類實現這些方法,所以它并不是一個完整的類定義。 它說類中有一個方法,但是并沒有實現,因為根據不同的情況可能實現不同,但是部分方法有通用的實現,因此只寫這一部分方法。 還有一種特殊的抽象類,就是所有的方法都是抽象的方法,額,其實這在JAVA一般叫定義為"接口"。只是抽象類不能多繼承,接口可以"多繼承"。

額,寫完發(fā)現,受不同語言影響較大,一些詞用的比較亂,比如基類,父類,屬性,成員變量等。

2017年10月30日 00:30