亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Spring?依賴查找的使用小結(jié)

 更新時(shí)間:2023年12月18日 10:17:50   作者:TheBugKiller  
在不同的編程框架和容器中,依賴查找的方式可能會(huì)有所不同,本文主要介紹了Spring依賴查找的使用小結(jié),具有一定的參考價(jià)值,感興趣的可以了解一下

前言

源碼在我github的guide-spring倉(cāng)庫(kù)中,可以克隆下來 直接執(zhí)行。
我們本文主要來介紹依賴查找的使用示例

依賴查找

什么是依賴查找

依賴查找并不是 Spring 框架特有的概念,它是一種在軟件開發(fā)中獲取依賴對(duì)象的方式。它通常用于獲取運(yùn)行時(shí)需要的服務(wù)、組件或其他對(duì)象的引用。在面向?qū)ο缶幊讨校蕾囃ǔsw現(xiàn)為一個(gè)對(duì)象需要另一個(gè)對(duì)象的服務(wù)或功能。

在不同的編程框架和容器中,依賴查找的方式可能會(huì)有所不同。我們簡(jiǎn)單羅列一些常見的依賴查找的例子:

Java中的依賴查找

在純 Java 環(huán)境中,依賴查找通常通過構(gòu)造函數(shù)、方法參數(shù)或其他手段來獲得依賴對(duì)象的引用。
例如,通過在一個(gè)對(duì)象的構(gòu)造函數(shù)中傳遞另一個(gè)對(duì)象的引用:

public class MyClass {
    private DependencyClass dependency;

    public MyClass(DependencyClass dependency) {
        this.dependency = dependency;
    }

    // ...
}

Spring框架中的依賴查找

在Spring框架中,依賴查找通常通過 Spring 容器來實(shí)現(xiàn)。你可以使用ApplicationContextor BeanFactory 來獲取所需的 Bean 。

public class UseDependencyLookupDemo {

    public static void main(String[] args) throws Exception {
        BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/dependency-lookup.xml");
        // 1. 實(shí)時(shí)查找
        realtimeLookup(beanFactory);
    }
    private static void realtimeLookup(BeanFactory beanFactory) {
        // 名稱+類型
        User user = beanFactory.getBean("user", User.class);
        System.out.println("實(shí)時(shí)查找: " + user);
    }
}

或者,通過在類中使用@Autowired注解來自動(dòng)注入依賴:

@Service
public class MyService {
    @Autowired
    private DependencyClass dependency;

    // ...
}

Java EE中的依賴查找:

在Java EE環(huán)境中,你可以使用JNDI(Java Naming and Directory Interface)進(jìn)行依賴查找。通過JNDI,你可以在運(yùn)行時(shí)查找和獲取命名對(duì)象。

public class JNDIDependencyLookupDemo {
    public static void main(String[] args) throws NamingException {
        // 設(shè)置JNDI環(huán)境屬性
        Properties properties = new Properties();
        properties.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");
        properties.put(Context.PROVIDER_URL, "file:/META-INF/jndi");

        // 初始化InitialContext
        Context initialContext = new InitialContext(properties);

        // 在文件系統(tǒng)上查找一個(gè)名為 "user" 的對(duì)象
        User user = (User) initialContext.lookup("user");

        System.out.println("JNDI Lookup Result: " + user);
    }
}

依賴查找的方式

依賴查找的方式有很多,我們先看下 BeanFactory 的 接口定義:

public interface BeanFactory {

    Object getBean(String name) throws BeansException;

    <T> T getBean(String name, Class<T> requiredType) throws BeansException;

    <T> T getBean(Class<T> requiredType) throws BeansException;

    <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
  
    <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);

}

可以看出上述定義,我們可以通過 Bean 名稱、Bean 名稱 + 類型、類型等方式進(jìn)行依賴查找 Bean。下面我們分別從單一類型、集合類型、層次類型、延遲等方式依次展示依賴查找的示例。

單一類型的依賴查找

單一類型的查找,需要要求容器中同一類型的Bean只能有一個(gè)為 primary (BeanDefinition中的概念),我們可以看下 xml 配置示例

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user" class="com.markus.spring.ioc.overview.domain.User">
        <property name="id" value="1"/>
        <property name="username" value="markus zhang"/>
    </bean>
        <!-- 當(dāng)有多個(gè) User 時(shí),需要指出 其中一個(gè) Bean 的 primary屬性為 true 否則會(huì)出現(xiàn) NoUniqueBeanDefinitionException -->
    <bean id="user2" class="com.markus.spring.ioc.overview.domain.User" lazy-init="true" primary="true">
        <property name="id" value="2"/>
        <property name="username" value="markus zhang"/>
    </bean>

</beans>

我們來看下使用示例

public class UseDependencyLookupDemo {

    public static void main(String[] args) throws Exception {
        BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/dependency-lookup.xml");

        typeLookup(beanFactory);
    }

    /**
     * ========================按照 Bean 類型查找========================
     */

    /**
     * 單個(gè)Bean類型查找
     *
     * @param beanFactory
     */
    private static void typeLookup(BeanFactory beanFactory) {
        User user = beanFactory.getBean(User.class);
        System.out.println(user);
    }
}

集合類型的依賴查找

與單一類型查找的區(qū)別在于,它不需要指定 primary 并且 返回一個(gè) Map<String,T> 對(duì)象,key 為 Bean 的名稱,value 為 Bean 實(shí)例。

public class UseDependencyLookupDemo {

    public static void main(String[] args) throws Exception {
        BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/dependency-lookup.xml");
        // 4. 按照類型查找多個(gè)Bean
        collectionLookup(beanFactory);
    }

    /**
     * 根據(jù)集合類型查找
     */
    private static void collectionLookup(BeanFactory beanFactory) {
        if (beanFactory instanceof ListableBeanFactory) {
            ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;
            Map<String, User> userMap = listableBeanFactory.getBeansOfType(User.class);
            userMap.forEach((beanName, user) -> System.out.println("Bean name: " + beanName + ", User: " + user));
        }
    }
}

層次類型的依賴查找

層次性依賴查找,體現(xiàn)在父子容器中,我們一般可能體會(huì)不到,實(shí)際上 Spring MVC 的底層就涉及父子容器的概念,即 Root ApplicationContext 和 Dispatcher-Servlet ApplicationContext。這里不展開了。我們通過一個(gè)簡(jiǎn)單的示例來展示層次性依賴查找 Bean

package com.markus.spring.dependency.lookup;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.HierarchicalBeanFactory;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionReader;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @author: markus
 * @date: 2023/12/17 10:23 PM
 * @Description: {@link HierarchicalBeanFactory}
 * @Blog: https://markuszhang.com
 * It's my honor to share what I've learned with you!
 */
public class HierarchicalBeanFactoryDependencyDemo {
    public static void main(String[] args) {
        ConfigurableListableBeanFactory subBeanFactory = new DefaultListableBeanFactory();
        // 設(shè)置父容器
        subBeanFactory.setParentBeanFactory(createParent());

        // 展示 僅在當(dāng)前 Bean 容器中是否 存在
        System.out.println(displayContainBean(subBeanFactory, "user", true));
        // 展示 父子 Bean 容器中是否 存在(體現(xiàn)出 可繼承 BeanFactory 的示例 即 HierarchicalBeanFactory)
        System.out.println(displayContainBean(subBeanFactory, "user", false));

    }

    private static boolean displayContainBean(ConfigurableListableBeanFactory beanFactory, String beanName, boolean onlyLocal) {
        boolean result = beanFactory.containsLocalBean(beanName);
        if (!onlyLocal) {
            if (!result) {
                BeanFactory parentBeanFactory = beanFactory.getParentBeanFactory();
                if (parentBeanFactory != null) {
                    result = parentBeanFactory.containsBean(beanName);
                }
            }
        }
        return result;
    }

    private static ConfigurableListableBeanFactory createParent() {
        ConfigurableListableBeanFactory parentBeanFactory = new DefaultListableBeanFactory();
        BeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader((BeanDefinitionRegistry) parentBeanFactory);

        String location = "classpath:/META-INF/dependency-lookup.xml";
        // 加載 父容器 的 Bean 實(shí)例
        beanDefinitionReader.loadBeanDefinitions(location);
        return parentBeanFactory;
    }
}

延遲依賴查找

延遲依賴查找通常體現(xiàn)在懶加載 Bean 的場(chǎng)景,比如一些大資源的Bean希望在使用到的時(shí)候才會(huì)觸發(fā)初始化以達(dá)到降低服務(wù)啟動(dòng)時(shí)間的目的,這個(gè)時(shí)候就可以使用懶加載模式,而在我們依賴查找的時(shí)候,使用延遲依賴查找的時(shí)候,也不會(huì)觸發(fā) Bean 的初始化,只有在真正使用到對(duì)象的時(shí)候才會(huì)觸發(fā)初始化。(ps 比較繞,我們直接看例子)

因?yàn)?Bean 元信息配置比較特殊,我把 xml 配置也展示出來

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user2" class="com.markus.spring.ioc.overview.domain.User" lazy-init="true" primary="true">
        <property name="id" value="2"/>
        <property name="username" value="markus zhang"/>
    </bean>

    <bean id="factoryBean" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
        <property name="targetBeanName" value="user2"/>
    </bean>

</beans>

使用示例

public class UseDependencyLookupDemo {

    public static void main(String[] args) throws Exception {
        BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/dependency-lookup.xml");

        lazyLookup(beanFactory);
    }

    /**
     * 延遲查找
     */
    private static void lazyLookup(BeanFactory beanFactory) throws Exception {
        @SuppressWarnings("unchecked")
        ObjectFactory<User> factoryBean = (ObjectFactory<User>) beanFactory.getBean("factoryBean");
        System.out.println("延遲生效中....");
        System.out.println("延遲查找: " + factoryBean.getObject());
    }
 }

Spring內(nèi)建可查找的依賴

除了我們自己配置的Bean,我們還可以查找 Spring 框架內(nèi) 注冊(cè)的單例 Bean。具體如下:

  • environment Environment 外部化配置以及Profiles
  • systemProperties Properties Java系統(tǒng)屬性
  • systemEnvironment Map<String,String> 操作系統(tǒng)環(huán)境變量
  • messageSource MessageSource 國(guó)家化文案
  • lifecycleProcessor LifecycleProcessor Lifecycle Bean 處理器
  • applicationEventMulticaster ApplicationEventMulticaster Spring 事件廣播器
  • internalConfigurationAnnotationProcessor ConfigurationClassPostProcessor 處理 Spring 的配置類
  • internalAutowiredAnnotationProcessor AutowiredAnnotationBeanPostProcessor 處理 @Autowired 以及 @Value、@Inject注解
  • internalCommonAnnotationProcessor CommonAnnotationBeanPostProcessor 處理 JSR-250 注解,如 @Resource、@PostConstruct等
  • internalEventListenerProcessor EventListenerMethodProcessor 處理標(biāo)注 @EventListener 的 Spring 事件監(jiān)聽方法
  • internalEventListenerFactory DefaultEventListenerFactory 處理@EventListener 事件監(jiān)聽方法適配為 ApplicationListener

我們來看下示例:

package com.markus.spring.dependency.lookup;

import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.LifecycleProcessor;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.CommonAnnotationBeanPostProcessor;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.context.event.DefaultEventListenerFactory;
import org.springframework.context.event.EventListenerMethodProcessor;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.env.Environment;

import java.util.Properties;

/**
 * @author: markus
 * @date: 2023/12/17 10:54 PM
 * @Description: Spring 內(nèi)建依賴的 依賴查找示例
 * @Blog: https://markuszhang.com
 * It's my honor to share what I've learned with you!
 */
public class SpringInternalBeanDependencyLookDemo {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:/META-INF/dependency-lookup.xml");

        displaySpringInternalBean(context, Environment.class);
        displaySpringInternalBean(context, Properties.class);
        displaySpringInternalBeanByName(context, "systemEnvironment");
        displaySpringInternalBean(context, MessageSource.class);
        displaySpringInternalBean(context, LifecycleProcessor.class);
        displaySpringInternalBean(context, ApplicationEventMulticaster.class);

        // 關(guān)閉 Spring 容器上下文
        context.close();

        // 基于 注解驅(qū)動(dòng) 的應(yīng)用上下文
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
        annotationConfigApplicationContext.register(SpringInternalBeanDependencyLookDemo.class);
        annotationConfigApplicationContext.refresh();

        displaySpringInternalBean(annotationConfigApplicationContext, ConfigurationClassPostProcessor.class);
        displaySpringInternalBean(annotationConfigApplicationContext, AutowiredAnnotationBeanPostProcessor.class);
        displaySpringInternalBean(annotationConfigApplicationContext, CommonAnnotationBeanPostProcessor.class);
        displaySpringInternalBean(annotationConfigApplicationContext, EventListenerMethodProcessor.class);
        displaySpringInternalBean(annotationConfigApplicationContext, DefaultEventListenerFactory.class);

        annotationConfigApplicationContext.close();
    }

    private static void displaySpringInternalBean(ApplicationContext context, Class<?> type) {
        Object bean = context.getBean(type);
        System.out.println(bean);
    }

    private static void displaySpringInternalBeanByName(ApplicationContext context, String beanName) {
        Object bean = context.getBean(beanName);
        System.out.println(bean);
    }
}

可以看到上面我們引入了基于 Xml 驅(qū)動(dòng)的Spring應(yīng)用上下文以及基于 注解 驅(qū)動(dòng)的Spring應(yīng)用上下文來實(shí)現(xiàn) Spring 內(nèi)建 Bean 的依賴查找。
ps: 如果一個(gè)默認(rèn)的 ClassPathXmlAppplicationContext 不會(huì)包含ConfigurationClassPostProcessor、AutowiredAnnotationBeanPostProcessor等這些注解的依賴,需要我們?cè)?xml 配置文件中開啟 注解啟動(dòng),才會(huì)注冊(cè)進(jìn) Spring IoC容器中。
大家可能會(huì)有疑問,這些 Spring 內(nèi)建的 Bean 是什么時(shí)候被注冊(cè)進(jìn)去呢?這里給下源碼位置,感興趣的可以自行查看:

org.springframework.context.support.AbstractApplicationContext#prepareBeanFactory
org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)

依賴查找的常見異常

下面這些就是場(chǎng)景的在使用依賴查找的時(shí)候可能會(huì)觸發(fā)的異常,都是 BeansException 的子類型。場(chǎng)景比較清晰,這里就不寫具體的示例了。

異常類型觸發(fā)條件場(chǎng)景舉例
NoSuchBeanDefinitionException當(dāng)查找 Bean 不存在于 IoC 容器 時(shí)BeanFactory#getBean
NoUniqueBeanDefinitionException類型依賴查找時(shí),IoC 容器存在多 個(gè) Bean 實(shí)例BeanFactory#getBean(Class)
BeanInstantiationException當(dāng) Bean 所對(duì)應(yīng)的類型非具體類時(shí)BeanFactory#getBean
BeanCreationException當(dāng) Bean 初始化過程中Bean 初始化方法執(zhí)行異常時(shí)
BeanDefinitionStoreException當(dāng) BeanDefinition 配置元信息非 法時(shí)XML 配置資源無法打開時(shí)

本文總結(jié)

好了,到這就基本上把 Spring 依賴查找相關(guān)的知識(shí)點(diǎn)就總結(jié)完了,本文我們主要總結(jié)了依賴查找的幾種方式,包括單一類型、集合類型、層次性、延遲性以及 Spring 內(nèi)建 Bean 的依賴查找,并給出了 Spring 內(nèi)建 Bean 注冊(cè)的源碼位置,最后提到了依賴查找的幾個(gè)常見的異常,并給出了常見場(chǎng)景觸發(fā)的條件。

關(guān)于 Spring 依賴 還有依賴注入、依賴來源等知識(shí) 后面會(huì)跟進(jìn)梳理。

到此這篇關(guān)于Spring 依賴查找的使用小結(jié)的文章就介紹到這了,更多相關(guān)Spring 依賴查找內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • JAVA多線程Thread和Runnable的實(shí)現(xiàn)

    JAVA多線程Thread和Runnable的實(shí)現(xiàn)

    java中實(shí)現(xiàn)多線程有兩種方法:一種是繼承Thread類,另一種是實(shí)現(xiàn)Runnable接口。
    2013-03-03
  • Springboot 全局時(shí)間格式化三種方式示例詳解

    Springboot 全局時(shí)間格式化三種方式示例詳解

    時(shí)間格式化在項(xiàng)目中使用頻率是非常高的,當(dāng)我們的 API? 接口返回結(jié)果,需要對(duì)其中某一個(gè) date? 字段屬性進(jìn)行特殊的格式化處理,通常會(huì)用到 SimpleDateFormat? 工具處理,這篇文章主要介紹了3 種 Springboot 全局時(shí)間格式化方式,需要的朋友可以參考下
    2024-01-01
  • Spring中@Scheduled功能的使用方法詳解

    Spring中@Scheduled功能的使用方法詳解

    @Scheduled 由Spring定義,用于將方法設(shè)置為調(diào)度任務(wù),下面這篇文章主要給大家介紹了關(guān)于Spring中@Scheduled功能的使用方法,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-04-04
  • 淺談Java8新特性Predicate接口

    淺談Java8新特性Predicate接口

    這篇文章主要介紹了淺談Java8新特性Predicate接口,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有很好的幫助,需要的朋友可以參考下
    2021-05-05
  • SpringMVC自定義日期轉(zhuǎn)換器方式

    SpringMVC自定義日期轉(zhuǎn)換器方式

    這篇文章主要介紹了SpringMVC如何自定義日期轉(zhuǎn)換器問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • 關(guān)于各種排列組合java算法實(shí)現(xiàn)方法

    關(guān)于各種排列組合java算法實(shí)現(xiàn)方法

    這篇文章介紹了幾種用JAVA實(shí)現(xiàn)的排列組合算法,有需要的朋友可以參考一下
    2013-06-06
  • java中DelayQueue實(shí)例用法詳解

    java中DelayQueue實(shí)例用法詳解

    在本篇內(nèi)容里小編給大家分享的是一篇關(guān)于java中DelayQueue實(shí)例用法詳解內(nèi)容,有需要的朋友們可以跟著學(xué)習(xí)下。
    2021-01-01
  • 如何用Java模擬XN*2圖靈機(jī)

    如何用Java模擬XN*2圖靈機(jī)

    這篇文章主要介紹了如何用Java模擬XN*2圖靈機(jī)方法,感興趣的朋友可以參考下
    2021-04-04
  • Maven中optional標(biāo)簽用法詳解

    Maven中optional標(biāo)簽用法詳解

    這篇文章主要介紹了Maven中optional標(biāo)簽,文章中有詳細(xì)的代碼示例供大家參考,對(duì)大家的學(xué)習(xí)或工作有一定的參考價(jià)值,感興趣的小伙伴可以借鑒一下
    2023-05-05
  • Java中多態(tài)性的實(shí)現(xiàn)方式

    Java中多態(tài)性的實(shí)現(xiàn)方式

    這篇文章主要介紹了Java中多態(tài)性的實(shí)現(xiàn)方式,什么是多態(tài)?通過簡(jiǎn)單的一道題目幫大家理解java多態(tài)性,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-09-09

最新評(píng)論