zoukankan      html  css  js  c++  java
  • spring Bean装配的几种方式简单介绍

    Spring容器负责创建应用程序中的bean同时通过ID来协调这些对象之间的关系。作为开发人员,我们需要告诉Spring要创建哪些bean并且如何将其装配到一起。

    spring中bean装配有两种方式

    • 隐式的bean发现机制和自动装配
    • 在java代码或者XML中进行显示配置

    当然这些方式也可以配合使用。

    我们测试代码如下

    CompactDisc和MediaPlayer是两个接口 其中MediaPlayer的构造方法参数类型为CompactDisc。
    我们主要测试CompactDisc和MediaPlayer的实现有没有注入进来,同时MediaPlayer接口对于CompactDisc的依赖有没有满足
    package com.zcs;
    
    import com.zcs.service.CompactDisc;
    import com.zcs.service.MediaPlayer;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import static junit.framework.TestCase.assertEquals;
    import static junit.framework.TestCase.assertNotNull;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    //XML配置
    //@ContextConfiguration(locations ="spring-config.xml")
    //Java代码配置
    @ContextConfiguration(classes =CDPlayerConfig.class)
    public class CDPlayerTest {
        @Autowired
        private CompactDisc cd;
        @Autowired
        private MediaPlayer player;
        @Test
        public void cdShouldNotBeNull(){
            assertNotNull(cd);
        }
        @Test
        public void play(){
            assertEquals("Playing 哎呦不错哦 by 周杰伦",player.play());
        }
    
    }

    1、自动化装配

    Spring从两个角度来实现自动化装配:

    组件扫描(ComponentScan):自动发现应用上下文中所创建的bean

    自动装配(Autowired):自动满足bean之间的依赖

    CompactDisc接口类和实现类:

    public interface CompactDisc {
        String play();
    }
    @Component
    public class SgtPeppers implements CompactDisc { private String title="哎呦不错哦"; private String artist="周杰伦"; @Override public String play() { return "Playing "+title+" by "+artist; } }

    MediaPalyer接口类和实现类

    public interface MediaPlayer {
        String play();
    }
    @Component
    public class CDPlayer implements MediaPlayer {
        private CompactDisc cd ;
        @Autowired
        public CDPlayer(CompactDisc cd){
            this.cd=cd;
        }
        @Override
        public String play(){
          return cd.play();
        }
    }

    配置类CDPlayerConfig:

    @Configuration
    @ComponentScan
    public class CDPlayerConfig {
    
    }

    @ComponentScan作用是扫描带有@Component注解的类,并为其创建bean。默认是扫描同一包下的类,当然也可以加入参数,指定包名。

    如@ComponentScan(basePackages={"com.zcs"})或者@ComponentScan(basePackageClasses={CDPlayer.class,DVDPlayer.class})(即这些类所在的包)

    @Autowired满足自动依赖装配,可以作用在任何方法上面。

    XML形式的自动装配则修改测试类@ContextConfiguration,改成加载spring-config.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: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">
        <bean id="compactDisc" class="com.zcs.impl.SgtPeppers"></bean>
        <bean id="cdPlayer" class="com.zcs.impl.CDPlayer">
            <constructor-arg ref="compactDisc"></constructor-arg>
        </bean>
        <context:component-scan base-package="com.zcs">
    </beans>

     2、显示bean装配

    当想要将第三方库中的组件装配到你的应用中,在这种情况下是没有办法在它的类上面添加@Component和@Autowired注解的,因此就不能使用自动化装配的方案。

     只能选择java代码或者xml显示配置

    首先可以把两个实现类上的@Component,还有配置类中的@ComponentScan,CDPlayer类中方法上的@Autowired注解去掉。

    这个时候测试应该都通不过。

    Java代码方式:修改CDPlayerConfig配置类为:

    @Configuration
    public class CDPlayerConfig {
        @Bean
        public CompactDisc sgtPeppers(){
            return new SgtPeppers();
        }
        @Bean
        public MediaPlayer getCDPlayer(){
            return new CDPlayer(sgtPeppers());
        }
       //@Bean
        //public MediaPlayer getCDPlayer(CompactDisc compactDisc){
        //    return new CDPlayer(compactDisc);
        //}
    }

     再运行测试应该会通过了,解释下 @Bean注解告诉Spring这个方法将会返回一个对象,该对象要注册为Spring应用上下文中的bean。方法体中包含了最终生成bean实列的逻辑。

     第二个方法故意写的奇怪一点,看起来CompactDisc是通过调用sgtPeppers()方法得到的,但并非如此,Spring会拦截对sgtPeppers方法的调用,转而从上下文中直接获取该方法所创建的bean,而不是每次都对其进行实际的调用。

    比如:再添加一个方法(测试会通不过)

       @Bean
        public MediaPlayer anotherCDPlayer() {
            return new CDPlayer(sgtPeppers());
        }

    这两个方法依赖注入的CompactDisc将会是同一个bean。

    当然通过情况下用注释的方法更容易理解一点。

    XML方式

    首先CDPlayerTest为XML方式,同时修改spring-config.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: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">
        <bean id="compactDisc" class="com.zcs.impl.SgtPeppers"></bean>
        <bean id="cdPlayer" class="com.zcs.impl.CDPlayer">
            <constructor-arg ref="compactDisc"></constructor-arg>
        </bean>
        <context:component-scan base-package="com.zcs"/>
    </beans>

    组件扫描方式的配置不去掉也是没影响的。

    补充:

    复杂一点的构造方法

    修改SgtPeppers的构造方法

    public class SgtPeppers implements CompactDisc {
        private String title="哎呦不错哦";
        private String artist="周杰伦";
        private List<String> tracks=new ArrayList<>();
    
        public SgtPeppers(String title, String artist, List<String> tracks) {
            this.title = title;
            this.artist = artist;
            this.tracks = tracks;
        }
    
        @Override
        public String play() {
            return "Playing "+title+" by "+artist;
        }
    }

    同时修改spring-config.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: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">
        <bean id="compactDisc" class="com.zcs.impl.SgtPeppers">
            <constructor-arg index="0" value="雪狼湖"/>
            <constructor-arg index="1" value="张学友"/>
            <constructor-arg index="2">
                <list>
                    <value>不老的传说</value>
                    <value>爱是永恒</value>
                </list>
            </constructor-arg>
        </bean>
        <bean id="cdPlayer" class="com.zcs.impl.CDPlayer">
            <constructor-arg ref="compactDisc"></constructor-arg>
        </bean>
        <context:component-scan base-package="com.zcs"/>
    </beans>

    还有属性注入<property>,c和p命名空间使用就不细说了。对于xml的配置一般在java代码中也会有对应的配置。但显示配置用java代码会类型安全一点

     参考:spring实战第4版

  • 相关阅读:
    TXSQL:云计算时代数据库核弹头——云+未来峰会开发者专场回顾
    游戏场景下的DDoS风险分析及防护
    一站式机器学习平台TI-ONE是什么?——云+未来峰会开发者专场回顾
    带有Apache Spark的Lambda架构
    攻克数据库核心技术壁垒,实现百万级QPS的高吞吐
    想学大数据?大数据处理的开源框架推荐
    可怕!数据库竟然打破安迪-比尔定律
    什么?云数据库也能C位出道?
    协同过滤的R语言实现及改进
    Android代码规范----按钮单击事件的四种写法
  • 原文地址:https://www.cnblogs.com/zuochengsi-9/p/9047111.html
Copyright © 2011-2022 走看看