1. 程式人生 > 實用技巧 >Spring依賴查詢

Spring依賴查詢

Spring依賴查詢

延遲依賴查詢

import com.fly.demo.User;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;

/**
 * 延遲依賴查詢
 * 通過 {@link org.springframework.beans.factory.ObjectProvider} 進行依賴查詢
 */
public class ObjectProviderDemo {
    public static void main(String... args) {
        AnnotationConfigApplicationContext applicationContext
                = new AnnotationConfigApplicationContext();
        applicationContext.register(ObjectProviderDemo.class);
        applicationContext.refresh();

        ObjectProvider<String> objectProvider = applicationContext.getBeanProvider(String.class);
        // 只會得到一個,如多個取 Primary 的
        System.out.println(objectProvider.getObject());

        objectProvider.stream().forEach(System.out::println);

        ObjectProvider<User> userObjectProvider = applicationContext.getBeanProvider(User.class);
        User user = userObjectProvider.getIfAvailable(() -> {
            System.out.println("沒找到!新建一個");
            return new User();
        });
        System.out.println(user);



        applicationContext.close();
    }

    @Bean
    @Primary
    public String message1() {
        return "Message1";
    }

    @Bean
    public String message2() {
        return "Message2";
    }
}

層次性依賴

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

/**
 * 層次性依賴查詢示例
 * {@link HierarchicalBeanFactory}
 */
public class HierarchicalDependencyLookupDemo {
    public static void main(String... args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();
        // 設定 Parent BeanFactory
        HierarchicalBeanFactory parentBeanFactory = createParentBeanFactory();
        beanFactory.setParentBeanFactory(parentBeanFactory);

//        displayContainsLocalBean(beanFactory, "user");
//        displayContainsLocalBean(parentBeanFactory, "user");

        displayContainsBean(beanFactory, "user");
        displayContainsBean(parentBeanFactory, "user");

        // 啟動應用上下文
        applicationContext.refresh();

        // 關閉應用上下文
        applicationContext.close();
    }

    private static void displayContainsBean(HierarchicalBeanFactory beanFactory, String beanName) {
        System.out.printf("當前 BeanFactory[%s] 是否包含 Bean[name : %s] : %s\n", beanFactory, beanName,
                containsBean(beanFactory, beanName));
    }

    private static boolean containsBean(HierarchicalBeanFactory beanFactory, String beanName) {
        BeanFactory parentBeanFactory = beanFactory.getParentBeanFactory();
        if (parentBeanFactory instanceof HierarchicalBeanFactory) {
            HierarchicalBeanFactory parentHierarchicalBeanFactory = HierarchicalBeanFactory.class.cast(parentBeanFactory);
            if (containsBean(parentHierarchicalBeanFactory, beanName)) {
                return true;
            }
        }
        return beanFactory.containsLocalBean(beanName);
    }

    private static void displayContainsLocalBean(HierarchicalBeanFactory beanFactory, String beanName) {
        System.out.printf("當前 BeanFactory[%s] 是否包含 Local Bean[name : %s] : %s\n", beanFactory, beanName,
                beanFactory.containsLocalBean(beanName));
    }


    private static ConfigurableListableBeanFactory createParentBeanFactory() {
        // 建立 BeanFactory 容器
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
        // XML 配置檔案 ClassPath 路徑
        String location = "classpath:/META-INF/dependency-lookup-context.xml";
        // 載入配置
        reader.loadBeanDefinitions(location);
        return beanFactory;
    }
}

依賴查詢中的經典異常

異常型別 觸發條件(舉例) 場景舉例
NoSuchBeanDefinitionException 當查詢 Bean 不存在於 IoC 容器時 BeanFactory#getBean ObjectFactory#getObject
NoUniqueBeanDefinitionExceptio n 型別依賴查詢時,IoC 容器存在多 個 Bean 例項 BeanFactory#getBean(Cla ss)
BeanInstantiationException 當 Bean 所對應的型別非具體類時 BeanFactory#getBean
BeanCreationException 當 Bean 初始化過程中 Bean 初始化方法執行異常 時
BeanDefinitionStoreException 當 BeanDefinition 配置元資訊非法 時 XML 配置資源無法開啟時
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import javax.annotation.PostConstruct;

/**
 * BeanCreationException 初始化異常 示例
 */
public class BeanCreationExceptionDemo {
    public static void main(String... args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 註冊 BeanDefinition Bean Class 是一個 POJO 普通類,不過初始化方法回撥時丟擲異常
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(POJO.class);
        applicationContext.registerBeanDefinition("errorBean", beanDefinitionBuilder.getBeanDefinition());
        // 啟動應用上下文
        applicationContext.refresh();

        // 關閉應用上下文
        applicationContext.close();
    }

    static class POJO implements InitializingBean {
        @PostConstruct // CommonAnnotationBeanPostProcessor
        public void init() throws Exception {
            throw new Exception("init() : For purposes...");
        }

        @Override
        public void afterPropertiesSet() throws Exception {
            throw new Exception("afterPropertiesSet() : For purposes...");
        }
    }
}