zoukankan      html  css  js  c++  java
  • spring配置与使用

    自动化装配Bean

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

    1.组件扫描(component scanning):spring会自动发现应用上下文所创建的bean。

    2.自动装配(autowiring):spring自动满足spring之间的依赖。

      组件扫描和自动装配组合在一起就能发挥出强大的威力,能将你的显示配置降低到最少。

      例子:CD(compact disc)要插入(注入)到CD播放器中,CD播放器才有用。CD播放器依赖于CD才能完成它的使命。

      在Java中定义CD的概念。定义一个CD的接口CompactDisc。作为接口,它定义了CD播放器对一盘CD所能进行的操作。

    package soundsystem;

    public interface CompactDisc{
        void play();
    }
      定义一个带有@Component注解的CompactDisc的实现类SgtPeppers。(可以有多个实现)

    package soundsystem;
    import org.springframework.stereotype.Component;

    @Component
    public class SgtPeppers implements CompactDisc {
        private String title = "Sgt. Peppert's Lonely Hearts Club Band";
        private String artist = "The Beatles";
        public void play() {
            System.out.println("Playing "+ title + " by " + artist);
        }
    }
           SgtPeppers的具体内容并不重要。需要注意的是SgtPeppers类上使用了@Component注解,这个简单的注解表明该类会作为组件类,并告知Spring要为这个类创建bean。

           组件扫描默认是不启用的。我们还需要显式配置以下Spring,命令它去寻找带有@Component注解的类,并为其创建bean。下面的配置类完成了这项任务的最简洁配置。

    @ComponentScan注解启用了组件扫描。

    package soundsystem;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;

    @Configuration
    @ComponentScan //默认当前包为基础包
    public class CDPlayerConfig {
    }
           类CDPlayerConfig 通过Java代码定义了Spring的装配规则。如果没有其他配置的话,@ComponentScan默认会扫描与配置类相同的包。因为CDPlayerConfig类位于soundsystem包中,因此Spring将会扫描这个包及其所有子包,查找带有@Component注解的类。这样就能发现CompactDisc,并且会在Spring中自动为其创建一个bean。

    注释:@ComponentScan(设置组件扫描的基础包)

    @ComponentScan //默认当前包为基础包
    //@ComponentScan("soundsystem") //通过value属性指定基础包
    //@ComponentScan(basePackages={"soundsystem"}) //指定基础包
    //@ComponentScan(basePackages={"soundsystem", "video"}) //指定多个基础包
    public class CDPlayerConfig {}
         在上面的例子中,所设置的基础包是以String类型表示的。虽然这是可以的,但这种方法是类型不安全(not type-safe)的。如果你重构代码的话,那么所指定的基础包可能就会出现错误了。

           除了将包设置为简单的String类型之外,@ComponentScan还提供了另外一种方法,那就是将其指定为包中所包含的类或接口:

    @ComponentScan(basePackageClasses={CDPlayer.class,DVDPlayer.class)//这些类所在的包会作为组件扫描的基础包
           你可以考虑在包中创建一个用来进行扫描的空标记接口(marker interface)。通过标记接口的方式,你依然能够保持对重构友好的接口引用,但是可以避免引用任何实际的应用程序代码(在以后的重构中,这些应用代码有可能会从想要扫描的包中移除掉)。

           也可以通过XML来启用组件扫描。使用Spring context命名空间的<context:component-scan>元素。

    <?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">

    <context:component-scan base-package="soundsystem"/>

    </beans>
           通过为bean添加注解实现自动装配。借助Spring的@Autowired注解。

           下面的CDPlayer类,它的构造器上添加了@Autowired注解,表明当Spring创建CDPlayer bean的时候,会通过这个构造器来进行实例化并且会传入一个可以设置给CompactDisc类型的bean。

        通过自动装配,将一个CompactDisc注入到CDPlayer之中

    package soundsystem;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;

    @Component
    public class CDPlayer implements MedisPlayer {

    private CompactDisc cd;

    @Autowired
    public CDPlayer(CompactDisc cd){
    this.cd = cd;
    }

    public void play(){
    cd.play();
    }
    }
    package soundsystem;

    public interface MediaPlayer {
    void play();
    }
           @Autowired注解不仅能够用在构造器上,还能用在属性的Setter方法上。比如说,如果CDPlayer有一个setCompactDisc()方法,那么可以采用如下的注解形式进行自动装配:

    @Autowired
    public void setCompactDisc(CompactDisc cd){
    this.cd = cd;
    }
    注释:@Autowired

           在Spring初始化bean之后,它会尽可能得去满足bean的依赖。实际上,Setter方法并没有什么特殊之处。@Autowired注解可以用在类的任何方法上。假设CDPlayer类有一个insertDisc()方法,那么@Autowired能够像在setCompactDisc()上那样,发挥完全相同的作用:

    @Autowired
    public void insertDisc(CompactDisc cd){
    this.cd = cd;
    }
            不管是构造器、Setter方法还是其他的方法,Spring都会尝试满足方法参数上所声明的依赖。假如有且只有一个 bean匹配依赖需求的话,那么这个 bean 将会被装配进来。

           如果没有匹配的 bean,那么在应用上下文创建的时候,Spring会抛出一个异常。为了避免异常的出现,你可以将@Autowired 的 required 属性设置为 false: 

    @Autowired(required = false)
    public void CDPlayer(CompactDisc cd){
    this.cd = cd;
    }
           将 required属性设置为 false时,Spring尝试执行自动装配时,如果没有匹配的 bean的话,Spring将会让这个bean处于未装配的状态。但是,把 required属性设置为 false时,你需要谨慎对待。如果在你的代码中没有进行 null检查的话,这个处于未装配状态的属性有可能会出现 NullPointerException。

          如果有多个 bean都能满足依赖关系的话,Spring将会抛出一个异常,表明没有明确指定要选择哪个 bean进行自动装配。

           @Autowired是Spring特有的注解,你也可以考虑将其替换为@Inject。

    @Inject
    public CDPlayer(CompactDisc cd){
    this.cd = cd;
    }
           @Inject注解来源于Java依赖注入规范, 在自动装配中,Spring同时支持@Inject和@Autowired。尽管@Inject和@Autowired之间有着一些细微的差别,但是在大多数场景下,它们都是可以互相替换的。

           我们已经在CDPlayer的构造器中添加了@Autowired注解,Spring将把一个可分配给CompactDisc类型的bean自动注入进来。为了验证这一点,创建CDPlayerTest测试类,使其能够借助CDPlayer bean播放CD:

    package soundsystem;

    import static org.junit.Assert.*;
    import org.junit.Rule;
    import org.junit.Test;
    import org.junit.contrib.java.lang.system.StandardOutputStreamLog;
    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;

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = CDPlayerConfig.class)
    public class CDPlayerTest {

    @Rule
    public final StandardOutputStreamLog log = new StandardOutputStreamLog ();

    @Autowired
    private MediaPlayer player;
    @Autowired
    private CompactDisc cd;

    @Test
    public void cdShouldNotBeNull(){
    assertNotNull(cd);
    }

    @Test
    public void play(){
    player.play();
    assertEquals(
    "Playing Sgt. Pepper's Lonely Hearts Club Band by The Beatles ",
    log.getLog());
    }
    }
           现在,除了注入CompactDisc,我们还将CDPlayer bean注入到测试代码的player成员变量之中(它是更为通用的MediaPlayer类型)。在play()测试方法中,我们可以调用CDPlayer的play()方法,并断言它的行为与你的预期一致。

    注意:

           在测试代码中使用System.out.println()是稍微有点棘手的事情。因此,该样例中使用了StandardOutputStreamLog,这是来源于System Rules库的一个JUnit规则,该规则能够基于控制台的输出编写断言。在这里,我们断言SgtPeppers.play()方法的输出被发送到了控制台上。

    参考原文:https://blog.csdn.net/qq_37311639/article/details/81587676

  • 相关阅读:
    NO29 用户提权sudo配置文件详解实践--志行为审计
    NO28 第四关考试题
    NO27 定时任务
    NO26 Linux的文件权限--chmod--Linux删除文件说明--suid--sgid
    NO25 三剑客之SED行天下
    NO24 第三关--企业面试题
    gcc编译错误表
    C++的精髓——虚函数
    gcc 优化选项 -O1 -O2 -O3 -Os 优先级,-fomit-frame-pointer
    正确使用#include和前置声明(forward declaration)
  • 原文地址:https://www.cnblogs.com/hechunhang/p/10864670.html
Copyright © 2011-2022 走看看