作者: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" 即可