Spring中的依賴查找和依賴注入


作者:Grey

原文地址: Spring中的依賴查找和依賴注入

依賴查找

Spring IoC 依賴查找分為以下幾種方式

  • 根據 Bean 名稱查找

    • 實時查找
    • 延遲查找
  • 根據 Bean 類型查找

    • 單個 Bean 對象
    • 集合 Bean 對象
  • 根據 Bean 名稱 + 類型查找

  • 根據 Java 注解查找

    • 單個 Bean 對象
    • 集合 Bean 對象

以下示例基於spring-framework 5.2.13.RELEASE 版本, 通過Maven管理項目

根據Bean名稱實時查找

pom.xml 文件引入如下依賴


<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
</dependency>

定義一個User作為Domain

public class User {
    private Long id;
    private String name;
    // set / get / toString方法略
}

在resources目錄下建立META—INF目錄,同時新建一個dependency-lookup.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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

</beans>

在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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user" class="org.snippets.spring.ioc.overview.dependency.domain.User">
        <property name="id" value="1"/>
        <property name="name" value="張三"/>
    </bean>

</beans>

新建測試類

package org.snippets.spring.ioc.overview.dependency.lookup;

/**
 * 通過名稱查找
 */
public class DependencyLookup {
    public static void main(String[] args) {
        BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/dependency-lookup.xml");
        lookupRealtime(beanFactory);
    }

    // 實時查找(按Bean名稱)
    private static void lookupRealtime(BeanFactory beanFactory) {
        User user = (User) beanFactory.getBean("user");
        System.out.println(user);
    }
}

輸出結果

User{id=1, name='張三'}

根據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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user" class="org.snippets.spring.ioc.overview.dependency.domain.User">
        <property name="id" value="1"/>
        <property name="name" value="張三"/>
    </bean>
    <bean id="objectFactory" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
        <property name="targetBeanName" value="user"/>
    </bean>
</beans>

新建測試類


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

    // 延遲查找(按Bean名稱)
    private static void lookupLazy(BeanFactory beanFactory) {
        ObjectFactory<User> objectFactory = (ObjectFactory<User>) beanFactory.getBean("objectFactory");
        User user = objectFactory.getObject();
        System.out.println(user);
    }
}

運行結果

User{id=1, name='張三'}

根據Bean類型查找單個對象


private static void lookupByTypeSingle(BeanFactory beanFactory){
        User user=beanFactory.getBean(User.class);
        System.out.println(user);
        }

根據Bean類型查詢集合對象

private static void lookupByTypeCollection(BeanFactory beanFactory){
      if(beanFactory instanceof ListableBeanFactory){
        ListableBeanFactory beanFactory1=(ListableBeanFactory)beanFactory;
        Map<String, User> users=beanFactory1.getBeansOfType(User.class);
        System.out.println(users);
      }
}

根據Java注解來查詢多個對象

首先我們定義一個注解@Super

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Super { }

然后我們定義一個User的子類SuperUser,並標注@Super注解

@Super
public class SuperUser extends User {
    private String address;
    // set / get / toString方法忽略
}

我們在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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user" class="org.snippets.spring.ioc.overview.dependency.domain.User">
        <property name="id" value="1"/>
        <property name="name" value="張三"/>
    </bean>
    <bean id="superUser" class="org.snippets.spring.ioc.overview.dependency.domain.SuperUser" parent="user"
          primary="true">
        <property name="address" value="廣州"/>
    </bean>
    <bean id="objectFactory" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
        <property name="targetBeanName" value="user"/>
    </bean>
</beans>

如果通過User.class類型來找Bean,可能會找到SuperUser和User兩個,但是加了Primary="true"這個配置,則只會找superUser這個Bean

接下來就是通過注解來找到Bean的代碼

    private static void lookupByAnnotations(BeanFactory beanFactory) {
        if (beanFactory instanceof ListableBeanFactory) {
            ListableBeanFactory beanFactory1 = (ListableBeanFactory) beanFactory;
            Map<String, User> users = (Map) beanFactory1.getBeansWithAnnotation(Super.class);
            System.out.println(users);
        }
    }

打印結果:

{superUser=SuperUser{address='廣州'} User{id=1, name='張三'}}

依賴注入

Spring IoC 依賴注入分為以下幾種方式

  • 根據 Bean 名稱注入

  • 根據 Bean 類型注入

    • 單個 Bean 對象
    • 集合 Bean 對象
  • 注入容器內建 Bean 對象

  • 注入非 Bean 對象

  • 注入類型

    • 實時注入
    • 延遲注入

增加UserRepository


public class UserRepository {
    private Collection<User> users; // 自定義Bean
    private BeanFactory beanFactory; // 內建非 Bean(依賴)
    private ObjectFactory<ApplicationContext> objectFactory;
    // 省略 set/get/toString方法
}

首先我們新建一個配置文件dependency-injection.xml

引入上一例中的dependency-lookup.xml,並增加一個Bean的配置, 並且配置手動注入這個Bean中屬性信息

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

    <import resource="dependency-lookup.xml"/>
    <bean id="userRepository"
          class="org.snippets.spring.ioc.overview.dependency.repo.UserRepository"
          > 
        <!-- 手動注入 -->
        <property name="users">
             <util:list>
                 <ref bean="user"/>
                 <ref bean="superUser"/>
             </util:list>
         </property>
    </bean>
</beans>

測試

public class DependencyInjection {
    public static void main(String[] args) {
        BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/dependency-injection.xml");
        UserRepository userRepository = beanFactory.getBean("userRepository", UserRepository.class);
        System.out.println(userRepository.getUsers()); 
    }
}

可以打印出注入的user信息

也可以實現自動注入,我們以按類型自動注入為例,修改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" xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">

    <import resource="dependency-lookup.xml"/>
    <bean id="userRepository"
          class="org.snippets.spring.ioc.overview.dependency.repo.UserRepository"
          autowire="byType"> <!-- 自動注入-->
    </bean>
</beans>

增加autowire="byType" 即可

完整代碼

Github

參考資料

小馬哥講Spring核心編程思想


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM