Skip to content

Spring如何组装Bean #16

@superstonne

Description

@superstonne

依赖注入的本质就是控制Bean的生成方式。原始的编程方式中,在代码未运行之前,Bean的具体实现类已经是确定,在依赖注入的编程思想中,Bean的实现类是代码运行时注入到需求方的。
那么Spring是如何帮助我们实现依赖注入的呢?IOC容器为我们提供了四种方式来实现依赖注入:

自动搜索组装Bean

如果需要Spring自动帮助我们搜索组装Bean,则需要设置Bean的搜索位置。

  • 依赖于Java的Bean搜索位置配置,可以设置basePackages和 basePackageClasses
    image
    image

  • 设置好Bean的搜索位置以后,则应该在相应的位置使用Component(Spring提供)或者Named(Java提供)注解声明我们的Bean
    image
    image

  • 注解好Bean以后,接下来就是在需要使用的地方,注解Autowired(Spring 提供)或者Inject(Java提供)为自动注入

    @Autowired
    private Robot sayHelloRobot;
    @Inject
    private Robot sayHiRobot;

    @Autowired
    private Robot superRobot;

用Java Bean来组装Bean

当我们使用第三方的类库的时候,此时我们没有源代码,因此注解的方式组装Bean此时不能使用,这时候Java Bean来组装Bean是一个方案。

@Configuration
public class RobotConfig {

    @Bean(name = {"notSayHello", "sayHelloRobot"})
    public SayHelloRobot sayHelloRobot() {
        return new SayHelloRobot();
    }
    @Bean
    public SayHiRobot sayHiRobot() {
        return new SayHiRobot();
    }

    @Bean
    public SuperRobot superRobot() {
        return new SuperRobot(sayHelloRobot(), sayHiRobot());
    }

    @Bean
    public SuperRobot superRobot(SayHelloRobot sayHelloRobot, SayHiRobot sayHiRobot) {
        return new SuperRobot(sayHelloRobot, sayHiRobot);
    }

    @Bean
    public Robot getSayHelloRobot() {
        int choice = (int) Math.floor(Math.random() * 4);
        if (choice == 0) {
            return new SayHelloRobot();
        } else if (choice == 1) {
            return new SayHiRobot();
        } else if (choice == 2) {
            return new SuperRobot(sayHelloRobot(), sayHiRobot());
        } else {
            return new Robot() {
                @Override
                public void say() {
                    System.out.println("No name robot.");
                }
            };
        }
    }
}

如上,我们使用Configuration注解来声明这是一个Sping的配置Bean,使用Bean注解来告诉Spring这个方法声明的是一个Bean,方法返回Bean的实例。默认为单例,声明的时候可以加一个字符串参数,来指定几个名字,每个名字获得的Bean是同一个实例。如果不指定名字,则默认使用方法名字为Bean的名字。
从getSayHelloRobot方法,我们可以看到:使用JavaBean的组装方式,我们向外提供的Bean可以更加灵活的组装Bean。

用XML来组装Bean

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:c="http://www.springframework.org/schema/c"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
    <!--<context:component-scan base-package="org.jinlong.study.spring.autowiring" />-->
    <bean id="sayHelloRobot" class="org.jinlong.study.spring.autowiring.SayHelloRobot"></bean>
    <bean id="sayHiRobot" class="org.jinlong.study.spring.autowiring.SayHiRobot"></bean>
    <bean id="superRobot" class="org.jinlong.study.spring.autowiring.SuperRobot">
        <constructor-arg ref="sayHelloRobot"/>
        <constructor-arg ref="sayHiRobot"/>
    </bean>
    <bean id="superRobot2" class="org.jinlong.study.spring.autowiring.SuperRobot"
          c:_0-ref="sayHelloRobot"
          c:_1-ref="sayHiRobot"/>
    <bean id="namedRobot" class="org.jinlong.study.spring.autowiring.NamedRobot" c:name="Nick" c:gender="Boy"/>
    <bean id="namedRobot1" class="org.jinlong.study.spring.autowiring.NamedRobot">
        <constructor-arg value="name1"/>
        <constructor-arg><null/></constructor-arg>
    </bean>
    <bean id="namedRobot2" class="org.jinlong.study.spring.autowiring.NamedRobot" c:_0="0" c:_1="1"/>
    <bean id="manyNamesRobot" class="org.jinlong.study.spring.autowiring.ManyNamesRobot">
        <constructor-arg>
            <list>
                <value>name1</value>
                <value>name2</value>
                <value>name3</value>
            </list>
        </constructor-arg>
    </bean>
    <bean id="manyNamesRobot1" class="org.jinlong.study.spring.autowiring.ManyNamesRobot">
        <property name="names">
            <list>
                <value>name1</value>
                <value>name2</value>
                <value>name3</value>
            </list>
        </property>
    </bean>
    <util:list id="name-list">
        <value>name1 from util list</value>
        <value>name2 from util list</value>
        <value>name3 from util list</value>
    </util:list>
    <bean id="manyNamesRobot2" class="org.jinlong.study.spring.autowiring.ManyNamesRobot" p:names-ref="name-list"/>
</beans>

如上展示了使用XML来组装的Bean的方式。

  • 构造器注入 或者 c:_0-ref
  • 属性注入 或者 p:names-ref="name-list"

用Java Bean 和 XML 混合的方式来组装Bean

  • 假如我们使用了基于JavaBean的组装方式,但是有一部分老的代码是使用XML组装Bean来完成的,那么我们可以在JavaBean的配置中引入XML方式的配置。
@Configuration
//@ComponentScan(basePackages = {"org.jinlong.study.spring.autowiring"})
//@ComponentScan(basePackageClasses = {Robot.class})
@ImportResource({"classpath:spring.xml"})
public class RobotConfig {
}
  • 如果我们希望在XML的配置中引入基于JavaBean的配置或者其他的XML的配置
<bean class="org.jinlong.study.spring.config.RobotConfig"/>
<import resource="service-jms.xml"/>

如上即可将基于Java和XML的配置统一到一起。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions