国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

重拾-Spring-IOC

GraphQuery / 3138人閱讀

摘要:為何重拾使用了多年,但是對其底層的一些實現還是一知半解,一些概念比較模糊故決定重新拾起,加深對的認識。小結是在完成創建后對其進行后置處理的接口是在完成實例化對其進行的后置處理接口是框架底層的核心接口,其提供了創建,獲取等核心功能。

為何重拾

使用了 Spring 多年,但是對其底層的一些實現還是一知半解,一些概念比較模糊;故決定重新拾起,加深對 Spring 的認識。

重拾計劃 spring 版本說明

Spring 在經過多年的演進過程中,其功能越來越豐富,組件越來越多;為了避免在閱讀源碼的過程中深陷泥潭中,決定采用最原始的版本 1.0; 但又不局限于 1.0 版本。

spring ioc spring aop spring 事務管理 spring orm 集成 實現分析 Spring 容器啟動
在本文中,通過常用的構造 ClassPathXmlApplicationContext 實例來作為對 Spring 實現分析的入口
    ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

通過調用鏈追蹤,Spring 容器啟動核心操作由 AbstractApplicationContext 類中 refresh 方法實現

public void refresh() throws BeansException {
    this.startupTime = System.currentTimeMillis();

    // tell subclass to refresh the internal bean factory
    // 完成 xml 配置文件的解析, 解析 bean 標簽生成 BeanDefinition 對象,并注冊到 BeanFactory
    refreshBeanFactory();
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();

    // configure the bean factory with context semantics
    beanFactory.registerCustomEditor(Resource.class, new ContextResourceEditor(this));
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    beanFactory.ignoreDependencyType(ResourceLoader.class);
    beanFactory.ignoreDependencyType(ApplicationContext.class);
    postProcessBeanFactory(beanFactory);

    // invoke factory processors registered with the context instance
    // 獲取內置 BeanFactoryPostProcessor 實例,并遍歷調用 postProcessBeanFactory 方法
    // 對 BeanFactory 進行后置處理
    for (Iterator it = getBeanFactoryPostProcessors().iterator(); it.hasNext();) {
        BeanFactoryPostProcessor factoryProcessor = (BeanFactoryPostProcessor) it.next();
        factoryProcessor.postProcessBeanFactory(beanFactory);
    }

    if (getBeanDefinitionCount() == 0) {
        logger.warn("No beans defined in ApplicationContext [" + getDisplayName() + "]");
    }
    else {
        logger.info(getBeanDefinitionCount() + " beans defined in ApplicationContext [" + getDisplayName() + "]");
    }

    // invoke factory processors registered as beans in the context
    // 從 Bean Definition 集合中查找 BeanFactoryPostProcessor 定義并實例化
    // 獲取 BeanFactoryPostProcessor 實例,并遍歷調用 postProcessBeanFactory 方法
    // 對 BeanFactory 進行后置處理
    invokeBeanFactoryPostProcessors();

    // register bean processor that intercept bean creation
    // 從 Bean Definition 集合中查找 BeanPostProcessor 類定義實例化并注冊到 BeanFactory 中
    registerBeanPostProcessors();

    // initialize message source for this context
    initMessageSource();

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

    // check for listener beans and register them
    refreshListeners();

    // instantiate singletons this late to allow them to access the message source
    // 對 Bean Definition 中單例且非延遲加載的類型進行實例化
    /**
     * bean 初始化過程如下:
     * 1 : bean 構造初始化
     * 2 : bean 屬性注入 (通過 bean definition 中的 property , autowire(byType, byName) 實現)
     * 3 : bean 若實現 BeanNameAware 接口,調用 setBeanName() 方法
     * 4 : bean 若實現 BeanFactoryAware 接口, 調用 setBeanFactory() 方法
     * 5 : 遍歷調用 BeanFactory 中注冊的 BeanPostProcessor 實例的 postProcessorBeforeInitialization() 方法
     * 6 : bean 若實現了 InitializingBean 接口,調用 afterPropertiesSet() 方法
     * 7 : bean 實例對應的 bean definition 中若定義了 init-method 屬性則調用對應的 init 方法
     * 8 : 遍歷調用 BeanFactory 中注冊的 BeanPostProcessor 實例的 postProcessorAfterInitialization() 方法
     */
    beanFactory.preInstantiateSingletons();

    // last step: publish respective event
    publishEvent(new ContextRefreshedEvent(this));
}

從源碼中可知,Spring 容器在啟動過程中,主要完成以下流程 :

通過加載指定的配置文件,完成 Bean Definition 解析并注冊到 BeanFactory 實例中

通過內置及應用自定義的 BeanFactoryPostProcessor 對 BeanFactory 實例進行后置處理

實例化應用自定義的 BeanPostProcessor 并注冊到 BeanFactory 實例中

實例化 Spring 容器中的 Bean

Spring 容器關閉
public void close() {
    logger.info("Closing application context [" + getDisplayName() + "]");

    // destroy all cached singletons in this context,
    // invoking DisposableBean.destroy and/or "destroy-method"
    // 銷毀容器中緩存的單例對象實例
    // 執行容器中 DisposableBean 的 destroy 方法
    getBeanFactory().destroySingletons();

    // publish respective event
    // 發送 spring 上下文關閉事件
    publishEvent(new ContextClosedEvent(this));
}

通過調用鏈追蹤,Spring 會遍歷容器中緩存的 bean 實例調用 destroyBean 方法。

protected void destroyBean(String beanName, Object bean) {
    logger.debug("Retrieving depending beans for bean "" + beanName + """);
    // 先銷毀所有依賴當前 bean 的實例
    String[] dependingBeans = getDependingBeanNames(beanName);
    if (dependingBeans != null) {
        for (int i = 0; i < dependingBeans.length; i++) {
            destroySingleton(dependingBeans[i]);
        }
    }

    if (bean instanceof DisposableBean) {
        // 如果 bean 實現了 DisposableBean 接口,將會執行 destroy 方法
        logger.debug("Calling destroy() on bean with name "" + beanName + """);
        try {
            ((DisposableBean) bean).destroy();
        }
        catch (Exception ex) {
            logger.error("destroy() on bean with name "" + beanName + "" threw an exception", ex);
        }
    }

    try {
        RootBeanDefinition bd = getMergedBeanDefinition(beanName, false);
        if (bd.getDestroyMethodName() != null) {
            // 如果 bean 定義了 destroy-method 屬性,將會調用自定義的銷毀方法
            logger.debug("Calling custom destroy method "" + bd.getDestroyMethodName() +
                                     "" on bean with name "" + beanName + """);
            invokeCustomDestroyMethod(beanName, bean, bd.getDestroyMethodName());
        }
    }
    catch (NoSuchBeanDefinitionException ex) {
        // ignore, from manually registered singleton
    }
}
下面將針對 Spring Bean 在容器啟動過程中的各個環節的實現進行詳細說明
Spring Bean 定義解析

通過對 refreshBeanFactory 方法的調用鏈追蹤,可以看到在 DefaultXmlBeanDefinitonParser 類的 registerBeanDefinitions 方法中實現對 Spring Bean 定義的解析及注冊。

public void registerBeanDefinitions(BeanDefinitionRegistry beanFactory, ClassLoader beanClassLoader,
                                                                            Document doc, Resource resource) {
    this.beanFactory = beanFactory;
    this.beanClassLoader = beanClassLoader;
    this.resource = resource;

    logger.debug("Loading bean definitions");
    Element root = doc.getDocumentElement();

    this.defaultLazyInit = root.getAttribute(DEFAULT_LAZY_INIT_ATTRIBUTE);
    logger.debug("Default lazy init "" + this.defaultLazyInit + """);
    this.defaultDependencyCheck = root.getAttribute(DEFAULT_DEPENDENCY_CHECK_ATTRIBUTE);
    logger.debug("Default dependency check "" + this.defaultDependencyCheck + """);
    this.defaultAutowire = root.getAttribute(DEFAULT_AUTOWIRE_ATTRIBUTE);
    logger.debug("Default autowire "" + this.defaultAutowire + """);

    NodeList nl = root.getChildNodes();
    int beanDefinitionCounter = 0;
    for (int i = 0; i < nl.getLength(); i++) {
        Node node = nl.item(i);
        if (node instanceof Element && BEAN_ELEMENT.equals(node.getNodeName())) {
            beanDefinitionCounter++;
            loadBeanDefinition((Element) node);
        }
    }
    logger.debug("Found " + beanDefinitionCounter + " <" + BEAN_ELEMENT + "> elements defining beans");
}
protected void loadBeanDefinition(Element ele) {
    // 獲取 bean 的 id, name 屬性
    String id = ele.getAttribute(ID_ATTRIBUTE);
    String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
    List aliases = new ArrayList();
    if (nameAttr != null && !"".equals(nameAttr)) {
        String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, BEAN_NAME_DELIMITERS, true, true);
        aliases.addAll(Arrays.asList(nameArr));
    }

    if (id == null || "".equals(id) && !aliases.isEmpty()) {
        id = (String) aliases.remove(0);
        logger.debug("No XML "id" specified - using "" + id + "" as ID and " + aliases + " as aliases");
    }

    // 解析 bean 標簽, 獲取 bean 配置的屬性,構造,是否懶加載 作用域
    AbstractBeanDefinition beanDefinition = parseBeanDefinition(ele, id);

    if (id == null || "".equals(id)) {
        if (beanDefinition instanceof RootBeanDefinition) {
            id = ((RootBeanDefinition) beanDefinition).getBeanClassName();
            logger.debug("Neither XML "id" nor "name" specified - using bean class name [" + id + "] as ID");
        }
        else {
            throw new BeanDefinitionStoreException(this.resource, "","Child bean definition has neither "id" nor "name"");
        }
    }

    logger.debug("Registering bean definition with id "" + id + """);
    // 將 bean definiton 注冊到 beanFactory
    this.beanFactory.registerBeanDefinition(id, beanDefinition);
    for (Iterator it = aliases.iterator(); it.hasNext();) {
        this.beanFactory.registerAlias(id, (String) it.next());
    }
}
protected AbstractBeanDefinition parseBeanDefinition(Element ele, String beanName) {
    String className = null;
    try {
        // 獲取 class 屬性
        if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
            className = ele.getAttribute(CLASS_ATTRIBUTE);
        }
        String parent = null;
        if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
            parent = ele.getAttribute(PARENT_ATTRIBUTE);
        }
        if (className == null && parent == null) {
            throw new BeanDefinitionStoreException(this.resource, beanName, "Either "class" or "parent" is required");
        }

        AbstractBeanDefinition bd = null;
        // 獲取屬性
        MutablePropertyValues pvs = getPropertyValueSubElements(beanName, ele);

        if (className != null) {
            // 獲取構造
            ConstructorArgumentValues cargs = getConstructorArgSubElements(beanName, ele);
            RootBeanDefinition rbd = null;

            if (this.beanClassLoader != null) {
                Class clazz = Class.forName(className, true, this.beanClassLoader);
                rbd = new RootBeanDefinition(clazz, cargs, pvs);
            }
            else {
                rbd = new RootBeanDefinition(className, cargs, pvs);
            }
            // 設置 bean dependOn
            if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
                String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
                rbd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, BEAN_NAME_DELIMITERS, true, true));
            }

            String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE);
            if (DEFAULT_VALUE.equals(dependencyCheck)) {
                dependencyCheck = this.defaultDependencyCheck;
            }
            rbd.setDependencyCheck(getDependencyCheck(dependencyCheck));

            // 設置 bean 自動注冊的方式 byType, byName or none
            String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
            if (DEFAULT_VALUE.equals(autowire)) {
                autowire = this.defaultAutowire;
            }
            rbd.setAutowireMode(getAutowireMode(autowire));

            // 設置 bean 的 init-method
            String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
            if (!initMethodName.equals("")) {
                rbd.setInitMethodName(initMethodName);
            }

            // 設置 bean 的 destroy-method
            String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
            if (!destroyMethodName.equals("")) {
                rbd.setDestroyMethodName(destroyMethodName);
            }

            bd = rbd;
        }
        else {
            bd = new ChildBeanDefinition(parent, pvs);
        }

        // 設置 bean 是否為單例
        if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
            bd.setSingleton(TRUE_VALUE.equals(ele.getAttribute(SINGLETON_ATTRIBUTE)));
        }

        // 是否懶加載
        String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
        if (DEFAULT_VALUE.equals(lazyInit) && bd.isSingleton()) {
            // just apply default to singletons, as lazy-init has no meaning for prototypes
            lazyInit = this.defaultLazyInit;
        }
        bd.setLazyInit(TRUE_VALUE.equals(lazyInit));

        bd.setResourceDescription(this.resource.getDescription());

        return bd;
    }
    catch (ClassNotFoundException ex) {
    }
    catch (NoClassDefFoundError err) {}
}
Spring 容器在將配置文件加載后,會解析 bean 標簽并通過其相應的屬性配置構造 BeanDefinition 對象,然后將 BeanDefinition 對象注冊添加到 BeanFactory 中。
Spring Bean 實例化
public void preInstantiateSingletons() {
    if (logger.isInfoEnabled()) {
        logger.info("Pre-instantiating singletons in factory [" + this + "]");
    }
    // 遍歷注冊的 bean definition
    for (Iterator it = this.beanDefinitionNames.iterator(); it.hasNext();) {
        String beanName = (String) it.next();
        if (containsBeanDefinition(beanName)) {
            RootBeanDefinition bd = getMergedBeanDefinition(beanName, false);
            // 如果 bean 定義為單例且非延遲加載的
            if (bd.isSingleton() && !bd.isLazyInit()) {
                // 判斷 bean 是否為 FactoryBean
                if (FactoryBean.class.isAssignableFrom(bd.getBeanClass())) {
                    FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);
                    if (factory.isSingleton()) {
                        getBean(beanName);
                    }
                }
                else {
                    // 若是普通 bean 則調用 getBean
                    getBean(beanName);
                }
            }
        }
    }
}
public Object getBean(String name) throws BeansException {
    String beanName = transformedBeanName(name);
    // eagerly check singleton cache for manually registered singletons
    // 檢查單例緩存池中 是否存在 bean 實例,如果有從緩存中獲取 bean 實例
    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);
        }
    }
}
protected Object createBean(String beanName, RootBeanDefinition mergedBeanDefinition) throws BeansException {
    if (mergedBeanDefinition.getDependsOn() != null) {
        for (int i = 0; i < mergedBeanDefinition.getDependsOn().length; i++) {
            // guarantee initialization of beans that the current one depends on
            getBean(mergedBeanDefinition.getDependsOn()[i]);
        }
    }

    // bean 初始化并包裝,也就是 new
    BeanWrapper instanceWrapper = null;
    if (mergedBeanDefinition.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
            mergedBeanDefinition.hasConstructorArgumentValues()) {
        instanceWrapper = autowireConstructor(beanName, mergedBeanDefinition);
    }
    else {
        instanceWrapper = new BeanWrapperImpl(mergedBeanDefinition.getBeanClass());
        initBeanWrapper(instanceWrapper);
    }
    Object bean = instanceWrapper.getWrappedInstance();

    // Eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like BeanFactoryAware.
    if (mergedBeanDefinition.isSingleton()) {
        // 單例的bean 則添加到緩存中
        addSingleton(beanName, bean);
    }
    // bean 屬性注入
    populateBean(beanName, mergedBeanDefinition, instanceWrapper);

    try {
        if (bean instanceof BeanNameAware) {
            // bean 若實現接口 BeanNameAware 則調用 setBeanName 方法
            ((BeanNameAware) bean).setBeanName(beanName);
        }

        if (bean instanceof BeanFactoryAware) {
            // bean 若實現接口 BeanFactoryAware 則調用 setBeanFactory 方法
            ((BeanFactoryAware) bean).setBeanFactory(this);
        }

        // 調用 BeanPostProcessor 執行 postProcessBeforeInitialization 方法
        bean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);
        // 若 bean 實現 InitializingBean 接口則執行 afterPropertiesSet 方法
        // 若 bean 定義中定義了 init-method 屬性則執行對應的init 方法
        invokeInitMethods(bean, beanName, mergedBeanDefinition);
        // 調用 BeanPostProcessor 執行 postProcessAfterInitialization 方法
        bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
    }
    catch (InvocationTargetException ex) {
        throw new BeanCreationException(mergedBeanDefinition.getResourceDescription(), beanName,
                                                                        "Initialization of bean failed", ex.getTargetException());
    }
    catch (Exception ex) {
        throw new BeanCreationException(mergedBeanDefinition.getResourceDescription(), beanName,
                                                                        "Initialization of bean failed", ex);
    }
    return bean;
}
從 bean 的實例化過程中,Spring 容器在啟動時只針對單例且非延遲加載的 bean 進行初始化;其他的 bean 只有在顯示調用 getBean() 方法時才去實例化;下面將會對實例化過程中的詳細過程進行說明。
Spring Bean 作用域
singleton 單例模式
Spring IoC 容器中只會存在一個共享的Bean實例,無論有多少個Bean引用它,始終指向同一對象。
    

    

Spring 1.0 中通過 bean 定義屬性 singleton="true" 表示單例; 在 Spring 2.x 之后版本改為定義屬性 scope="singleton", 同時兼容 1.0 的配置

prototype 原型模式
每次通過Spring容器獲取prototype定義的bean時,容器都將創建一個新的Bean實例,每個Bean實例都有自己的屬性和狀態
    

    

Spring 1.0 中通過 bean 定義屬性 singleton="false" 表示原型模式; 在 Spring 2.x 之后版本改為定義屬性 scope="prototype", 同時兼容 1.0 的配置

Spring Bean 生命周期

示例
public class LifecycleBean implements BeanNameAware, InitializingBean, BeanFactoryAware, ResourceLoaderAware, ApplicationContextAware, DisposableBean {

    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("set bean factory");
    }

    public void setBeanName(String name) {
        System.out.println("set bean name");
    }

    public void afterPropertiesSet() throws Exception {
        System.out.println("Initializing Bean afterPropertiesSet");
    }

    public void setApplicationContext(ApplicationContext context) throws BeansException {
        System.out.println("set application context");
    }

    public void setResourceLoader(ResourceLoader resourceLoader) {
        System.out.println("set resource loader");
    }

    public void init () {
        System.out.println("do init method");
    }

    public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
        System.out.println("post Process Before Initialization");
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String name) throws BeansException {
        System.out.println("post Process After Initialization");
        return bean;
    }

    public void destroy() throws Exception {
        System.out.println("do destroy ");
    }

    public void destroyMethod() throws Exception {
        System.out.println("do destroy method");
    }
}
public class PostProcessor implements BeanPostProcessor {
    public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
        if (bean instanceof LifecycleBean) {
            ((LifecycleBean) bean).postProcessBeforeInitialization(bean, name);
        }
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String name) throws BeansException {
        if (bean instanceof LifecycleBean) {
            ((LifecycleBean) bean).postProcessAfterInitialization(bean, name);
        }
        return bean;
    }
}

spring 配置文件如下


    

    

運行結果如下:

set bean name
set bean factory
set resource loader
set application context
post Process Before Initialization
Initializing Bean afterPropertiesSet
do init method
post Process After Initialization
do destroy 
do destroy method
Spring Bean 注入方式
構造注入

    
        
    


當 bean 定義配置如以上方式的時候,會觸發 autowireConstructor (詳細實現參考源碼吧)

BeanWrapper instanceWrapper = null;
if (mergedBeanDefinition.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
        mergedBeanDefinition.hasConstructorArgumentValues()) {

    instanceWrapper = autowireConstructor(beanName, mergedBeanDefinition);
}
byType 注入

當 bean 定義配置如以上方式的時候,會觸發 autowireByType 如下:

protected void autowireByType(String beanName, RootBeanDefinition mergedBeanDefinition,
                                                                BeanWrapper bw, MutablePropertyValues pvs) {
    // 查找 bean 存在可寫方法的非基本數據類型的成員變量
    String[] propertyNames = unsatisfiedObjectProperties(mergedBeanDefinition, bw);
    for (int i = 0; i < propertyNames.length; i++) {
        String propertyName = propertyNames[i];
        // look for a matching type
        // 獲取成員變量的類型
        Class requiredType = bw.getPropertyDescriptor(propertyName).getPropertyType();
        // 查找成員變量對應的 bean 實例
        Map matchingBeans = findMatchingBeans(requiredType);
        if (matchingBeans != null && matchingBeans.size() == 1) {
            // 成員變量查找到匹配的bean實例,有且只有一個的時候
            // 將屬性名和屬性值 添加到 PropertyValues 中
            pvs.addPropertyValue(propertyName, matchingBeans.values().iterator().next());
            if (logger.isDebugEnabled()) {
                logger.debug("Autowiring by type from bean name "" + beanName +
                                        "" via property "" + propertyName + "" to bean named "" +
                                        matchingBeans.keySet().iterator().next() + """);
            }
        }
        else if (matchingBeans != null && matchingBeans.size() > 1) {
            // 當存在多個同類型的實例時 拋出異常
            throw new UnsatisfiedDependencyException(beanName, propertyName,
                    "There are " + matchingBeans.size() + " beans of type [" + requiredType + "] for autowire by type. " +
                    "There should have been 1 to be able to autowire property "" + propertyName + "" of bean "" + beanName + "".");
        }
        else {
            if (logger.isDebugEnabled()) {
                logger.debug("Not autowiring property "" + propertyName + "" of bean "" + beanName +
                                        "" by type: no matching bean found");
            }
        }
    }
}
byName 注入

當 bean 定義配置如以上方式的時候,會觸發 autowireByName 如下:

protected void autowireByName(String beanName, RootBeanDefinition mergedBeanDefinition,
                                                                BeanWrapper bw, MutablePropertyValues pvs) {
    // 查找 bean 存在可寫方法的非基本數據類型的成員變量
    String[] propertyNames = unsatisfiedObjectProperties(mergedBeanDefinition, bw);
    for (int i = 0; i < propertyNames.length; i++) {
        String propertyName = propertyNames[i];
        // 在 Spring 容器中查找是否存在以 propertyName 命名的 bean definition
        if (containsBean(propertyName)) {
            // 實例化依賴的 bean, 并添加到 MutablePropertyValues 中
            Object bean = getBean(propertyName);
            pvs.addPropertyValue(propertyName, bean);
            if (logger.isDebugEnabled()) {
                logger.debug("Added autowiring by name from bean name "" + beanName +
                    "" via property "" + propertyName + "" to bean named "" + propertyName + """);
            }
        }
        else {
            if (logger.isDebugEnabled()) {
                logger.debug("Not autowiring property "" + propertyName + "" of bean "" + beanName +
                                        "" by name: no matching bean found");
            }
        }
    }
}
set 注入

    
        11
    

當 bean 定義配置如上,或者采用 byName, byType 的注入方式時,都會調用 applyPropertyValues 方法完成屬性的注入。(詳細實現參考源碼吧)

Spring Bean 注解式注入
自 Spring 2.5 版本之后,支持通過注解方式實現 Bean 的自動注入,譬如 @Autowired, @Resource 等注解

為了引入注解式自動注入, Spring 在 2.x 版本中新增了 InstantiationAwareBeanPostProcessor 接口,該接口繼承 BeanPostProcessor 并新增了方法 postProcessPropertyValues ; 該方法主要實現

Post-process the given property values before the factory applies them to the given bean
Autowired 注解
采用 Autowired 注解實現自動注入,需在配置文件中配置 AutowiredAnnotationBeanPostProcessor Bean
public AutowiredAnnotationBeanPostProcessor() {
    this.autowiredAnnotationTypes.add(Autowired.class);
    this.autowiredAnnotationTypes.add(Value.class);
    ClassLoader cl = AutowiredAnnotationBeanPostProcessor.class.getClassLoader();
    try {
        this.autowiredAnnotationTypes.add((Class) cl.loadClass("javax.inject.Inject"));
        logger.info("JSR-330 "javax.inject.Inject" annotation found and supported for autowiring");
    }
    catch (ClassNotFoundException ex) {
        // JSR-330 API not available - simply skip.
    }
}

AutowiredAnnotationBeanPostProcessor 構造可以看出其支持 @Autowired,@Value,@Inject 注解的自動注入。 下面大概看下其如何實現自動注入

public PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
    // 查找 bean 中需要自動注入的元數據,包括 field, method
    InjectionMetadata metadata = findAutowiringMetadata(bean.getClass());
    try {
        // 實現注入
        metadata.inject(bean, beanName, pvs);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
    }
    return pvs;
}
Resource 注解
采用 Resource 注解實現自動注入,需在配置文件中配置 CommonAnnotationBeanPostProcessor Bean
public CommonAnnotationBeanPostProcessor() {
    setOrder(Ordered.LOWEST_PRECEDENCE - 3);
    setInitAnnotationType(PostConstruct.class);
    setDestroyAnnotationType(PreDestroy.class);
    ignoreResourceType("javax.xml.ws.WebServiceContext");
}

CommonAnnotationBeanPostProcessor 構造可以看出,該類同時支持對注解 @PostConstruct, @PreDestroy 生效。

public PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
    // 查找 bean 中標注有 @Resource 注解的 Field, method
    InjectionMetadata metadata = findResourceMetadata(bean.getClass());
    try {
        // 實現注入
        metadata.inject(bean, beanName, pvs);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
    }
    return pvs;
}
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    // 查找 bean 定義中標注了 PostConstruct 注解的方法
    LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
    try {
        // 調用指定 post construct method
        metadata.invokeInitMethods(bean, beanName);
    }
    catch (InvocationTargetException ex) {
        throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
    }
    catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Couldn"t invoke init method", ex);
    }
    return bean;
}

public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
    // 查找 bean 定義中標注了 PreDestroy 注解的方法
    LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
    try {
        // 調用指定 destroy method
        metadata.invokeDestroyMethods(bean, beanName);
    }
    catch (InvocationTargetException ex) {
        String msg = "Invocation of destroy method failed on bean with name "" + beanName + """;
        if (logger.isDebugEnabled()) {
            logger.warn(msg, ex.getTargetException());
        }
        else {
            logger.warn(msg + ": " + ex.getTargetException());
        }
    }
    catch (Throwable ex) {
        logger.error("Couldn"t invoke destroy method on bean with name "" + beanName + """, ex);
    }
}
private LifecycleMetadata buildLifecycleMetadata(Class clazz) {
    final boolean debug = logger.isDebugEnabled();
    LinkedList initMethods = new LinkedList();
    LinkedList destroyMethods = new LinkedList();
    Class targetClass = clazz;

    do {
        LinkedList currInitMethods = new LinkedList();
        LinkedList currDestroyMethods = new LinkedList();
        // 遍歷 bean 的所有方法
        for (Method method : targetClass.getDeclaredMethods()) {
            if (this.initAnnotationType != null) {
                // 判斷 method 是否標注了 @PostConstruct 注解
                if (method.getAnnotation(this.initAnnotationType) != null) {
                    LifecycleElement element = new LifecycleElement(method);
                    currInitMethods.add(element);
                    if (debug) {
                        logger.debug("Found init method on class [" + clazz.getName() + "]: " + method);
                    }
                }
            }
            if (this.destroyAnnotationType != null) {
                // 判斷 method 是否標注了 @PreDestroy 注解
                if (method.getAnnotation(this.destroyAnnotationType) != null) {
                    currDestroyMethods.add(new LifecycleElement(method));
                    if (debug) {
                        logger.debug("Found destroy method on class [" + clazz.getName() + "]: " + method);
                    }
                }
            }
        }
        initMethods.addAll(0, currInitMethods);
        destroyMethods.addAll(currDestroyMethods);
        targetClass = targetClass.getSuperclass();
    }
    while (targetClass != null && targetClass != Object.class);

    return new LifecycleMetadata(clazz, initMethods, destroyMethods);
}
為了簡化 Spring 配置文件中的 bean 配置,Spring 提供了  標簽自動加載 AutowiredAnnotationBeanPostProcessor, CommonAnnotationBeanPostProcessor 等 bean。

在 spring-context 包 resources/META-INF 下的 spring.handlers 文件中配置如下:

http://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler
public class ContextNamespaceHandler extends NamespaceHandlerSupport {

    public void init() {
        registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
        registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
        registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
        registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
        registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
        registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
        registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
        registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
    }

}
public static Set registerAnnotationConfigProcessors(
            BeanDefinitionRegistry registry, Object source) {

    Set beanDefs = new LinkedHashSet(4);

    if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        // 加載注冊 AutowiredAnnotationBeanPostProcessor
        RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        // 加載注冊 RequiredAnnotationBeanPostProcessor
        RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
    if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        // 加載注冊 CommonAnnotationBeanPostProcessor
        RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
    if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition();
        try {
            ClassLoader cl = AnnotationConfigUtils.class.getClassLoader();
            def.setBeanClass(cl.loadClass(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME));
        }
        catch (ClassNotFoundException ex) {
            throw new IllegalStateException(
                    "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
        }
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    return beanDefs;
}

可以看出在 Spring 啟動時,通過解析 標簽,完成對 CommonAnnotationBeanPostProcessor, AutowiredAnnotationBeanPostProcessor 的加載注冊,進而實現通過注解方式的自動注入。

小結 BeanFactory & ApplicationContext

BeanFactoryPostProcessor & BeanPostProcessor

BeanFactoryPostProcessorApplicationContext 在 BeanFactory 完成創建后對其進行后置處理的接口

BeanPostProcessorBeanFactory 在 Bean 完成實例化對其進行的后置處理接口

BeanFactory & FactoryBean

BeanFactory 是 Spring 框架底層的核心接口,其提供了創建 bean,獲取 bean 等核心功能。

FactoryBean 是生產 bean 的一個模式,也就是以工廠模式的方式生產 bean。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/73511.html

相關文章

  • 重拾css(1)——寫在前邊的話

    摘要:本系列文章重拾主要參考王福朋知多少,結合自己的理解和學習需要,修改或添加了一些內容,難免有失偏頗,僅供自我學習參考之用。 工作中或多或少的寫一些css,但總感覺掌握的不夠扎實,時而需要查閱一下知識點。我想,一方面跟缺少科班出身式的系統學習有關,另一方面也苦于一直未尋覓到一套合我胃口教程。直到我讀到了王福朋css知多少系列文章,使我有了重新系統學習css的想法。 本系列文章(重拾css)...

    li21 評論0 收藏0
  • CSS魔法堂:重拾Border之——更廣闊的遐想

    摘要:也就是說我們操作的幾何公式中的未知變量,而具體的畫圖操作則由渲染引擎處理,而不是我們苦苦哀求設計師幫忙。 前言 ?當CSS3推出border-radius屬性時我們是那么欣喜若狂啊,一想到終于不用再添加額外元素來模擬圓角了,但發現border-radius還分水平半徑和垂直半徑,然后又發現border-top-left/right-radius的水平半徑之和大于元素寬度時,實際值會按比...

    lily_wang 評論0 收藏0
  • CSS魔法堂:重拾Border之——解構Border

    摘要:本系列將稍微深入探討一下那個貌似沒什么好玩的魔法堂重拾之解構魔法堂重拾之圖片作邊框魔法堂重拾之不僅僅是圓角魔法堂重拾之更廣闊的遐想解構說起我們自然會想起,而由條緊緊包裹著的邊組成,所以的最小操作單元是。 前言 ?當CSS3推出border-radius屬性時我們是那么欣喜若狂啊,一想到終于不用再添加額外元素來模擬圓角了,但發現border-radius還分水平半徑和垂直半徑,然后又發現...

    lingdududu 評論0 收藏0
  • spring-ioc流程源碼解析

    摘要:中的流程中的方法是啟動加載整個容器的關鍵方法。此函數第一步將流轉換成的,接下來就是解析,轉換成的然后注冊到中的一個中去。現在馬上就要開始解析了,真正的解析就在方法,是指,標簽就是此下的,所以會走。至此,的流程就走完了。 Spring中ioc的流程 AbstractApplicationContext 中的refresh()方法是啟動加載整個容器的關鍵方法。 在refresh()方法中...

    zorpan 評論0 收藏0
  • 架構~微服務

    摘要:接下來繼續介紹三種架構模式,分別是查詢分離模式微服務模式多級緩存模式。分布式應用程序可以基于實現諸如數據發布訂閱負載均衡命名服務分布式協調通知集群管理選舉分布式鎖和分布式隊列等功能。 SpringCloud 分布式配置 SpringCloud 分布式配置 史上最簡單的 SpringCloud 教程 | 第九篇: 服務鏈路追蹤 (Spring Cloud Sleuth) 史上最簡單的 S...

    xinhaip 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<