Spring依赖注入

依赖注入是IoC特性的一个重要功能,能自动将需要的Bean注入到对应的属性中,不需要手动进行初始化对象。
注入对象的方式主要有以下几种:

  • Set注入
  • 构造器注入

本文主要讲解Spring依赖注入的基本类型及来源。

本文所示案例基于Spring依赖查找代码结构,maven依赖配置略。

1.注入的类型

1.1 根据名称进行注入

定义一个仓储类UserRepository,如下:

public class UserRepository {

    private List<User> users;

    public List<User> getUsers() {
        return users;
    }

    public void setUsers(List<User> users) {
        this.users = users;
    }
}

在META-INF目录下新增spring-ioc-injection.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">

    <import resource="spring-ioc-overview.xml" />

    <bean id="userRepository" class="com.vielat.spring.ioc.injection.repository.UserRepository">
        <property name="users">
            <list>
                <ref bean="user" />
                <ref bean="adminUser" />
            </list>
        </property>
    </bean>
</beans>

在上一篇Spring依赖查找中,我们定义了两个对象:user和adminUser。这里直接新建一个配置文件,将上述配置通过import的方式进行引入。然后定义userRepository对象,属性值配置一个list,分别指向两个用户对象的引用。

测试类如下:

public class IoCInjectionDemo {

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

1.2 根据类型进行注入

上述根据名称进行注入,是通过引用Bean的名称的形式进行注入,但是这种方式是一种硬编码的形式。Spring提供了一种自动注入的方式,如下:

    <bean id="userRepository" class="com.vielat.spring.ioc.injection.repository.UserRepository" autowire="byType">
        <!--<property name="users">
            <list>
                <ref bean="user" />
                <ref bean="adminUser" />
            </list>
        </property>-->
    </bean>

通过autowire="byType"属性,Spring能自动查找该属性类型的Bean并进行注入,不需要手动配置注入的方式。

2. 注入的来源

我们了解了基本的注入之后,一定会比较疑惑:Spring注入的Bean从哪里来?以下从3个方面来讲述。

2.1 注入自定义Bean

以上述xml为例,定义的user、adminUser都属于自定义的Bean

2.2 注入非Spring Bean

UserRepository中新增如下属性:

public class UserRepository {

    ...
    private BeanFactory beanFactory;
    ...
    public BeanFactory getBeanFactory() {
        return beanFactory;
    }

    public void setBeanFactory(BeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }
}

配置文件不变,还是根据类型自动进行注入。在测试类中输入此对象:

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

输出结果如下:

org.springframework.beans.factory.support.DefaultListableBeanFactory@22f71333: defining beans [user,adminUser,objectFactory,userRepository]; root of factory hierarchy
org.springframework.context.support.ClassPathXmlApplicationContext@7e6cbb7a, started on Wed Jan 04 22:15:55 CST 2023
false

从上述执行结果可以看出,Spring自动注入的BeanFactory是一个内建的Bean,并不是我们自己初始化的BeanFactory。

如果通过我们初始化的容器BeanFactory去获取BeanFactory是获取不到的。

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

运行结果如下:

Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.beans.factory.BeanFactory' available
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:351)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1126)

2.3 注入内建的Bean

在UserRepository新增如下属性:

public class UserRepository {

    ...

    private ObjectFactory<User> objectFactory;
    
    private ObjectFactory<ApplicationContext> applicationContextObjectFactory;

    ...
public ObjectFactory<User> getObjectFactory() {
        return objectFactory;
    }

    public void setObjectFactory(ObjectFactory<User> objectFactory) {
        this.objectFactory = objectFactory;
    }

    public ObjectFactory<ApplicationContext> getApplicationContextObjectFactory() {
        return applicationContextObjectFactory;
    }

    public void setApplicationContextObjectFactory(ObjectFactory<ApplicationContext> applicationContextObjectFactory) {
        this.applicationContextObjectFactory = applicationContextObjectFactory;
    }
}

测试类如下:

public static void main(String[] args) {
        BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/spring-ioc-injection.xml");
        UserRepository userRepository = (UserRepository) beanFactory.getBean("userRepository");

        ObjectFactory objectFactory = userRepository.getObjectFactory();
        System.out.println(objectFactory.getObject());

        ObjectFactory applicationContextObjFactory = userRepository.getApplicationContextObjectFactory();
        System.out.println(applicationContextObjFactory.getObject());
        System.out.println(applicationContextObjFactory.getObject() == beanFactory);

        System.out.println(beanFactory.getBean(Environment.class));
    }

输出结果如下:

AdminUser{address='广州'} User{id=1, name='Michael'}
org.springframework.context.support.ClassPathXmlApplicationContext@7e6cbb7a, started on Wed Jan 04 22:29:23 CST 2023
true
StandardEnvironment {activeProfiles=[], defaultProfiles=[default], propertySources=[PropertiesPropertySource {name='systemProperties'}, SystemEnvironmentPropertySource {name='systemEnvironment'}]}

这次注入的ApplicationContext就是我们自己初始化出来的容器对象。

上一篇:Spring依赖查找

posted @ 2023-01-04 22:54  生活咖啡  阅读(48)  评论(0编辑  收藏  举报