Skip to content

Spring如何组装Bean #16

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的配置统一到一起。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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