Spring学习系列(三) 通过Java代码装配Bean

上面梳理了通过注解来隐式的完成了组件的扫描和自动装配,下面来学习下如何通过显式的配置的装配bean

二、通过Java类装配bean

在前面定义了HelloWorldConfig类,并使用@ComponentScan和@Configuration注解,@Configuration注解表明了这个类是一个java配置类,该类用在获取Spring应用上下文时,告诉Spring创建bean的细节,通过@ComponentScan,我们启用了Spring的自动组件扫描,现在就让我们来看如果通过java类来显式的配置bean,下面我们通过一个音乐播放器的案例来实践一下。

我们播放音乐,首先需要一个播放器,然后需要音乐资源,首先我们定义一个播放器接口和音乐资源接口

package com.seven.springTest.service;

// 播放器
public interface MediaPlayer {
    void play();
}
package com.seven.springTest.service;

// 音乐资源
public interface MusicSource {

    void play();
}

本次播放音乐我们是光驱来播放cd音乐,下面我们来实现上面的接口,

package com.seven.springTest.service.impl;

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

import com.seven.springTest.service.MusicSource;
import com.seven.springTest.service.MediaPlayer;

//定义光驱播放器
public class CDPlayer implements MediaPlayer {

    @Autowired
    // 定义一个音乐资源,这里通过@Autowired来声明需要注入MusicSource的依赖
    private MusicSource cd ;

    @Override
    public void play() {
        //播放音乐
        cd.play();
    }
}

实现音乐资源为光盘

package com.seven.springTest.service.impl;
import com.seven.springTest.service.MusicSource;

public class CDSource implements MusicSource {

    private String title = "七里香";
    private String artist = "周杰伦";

    @Override
    public void play() {
        System.out.println("Playing " + title + " by " + artist);
    }
}

到目前为止我们已经完成播放器、音乐资源的接口定义和具体的实现,那么我们如果告诉Spring应该创建哪么bean,并为它们注入什么依赖呢?在第一部分,我们通过@Component注解来隐式的告诉Spring,现在我们通过java类来配置bean组件。

@Bean

@Bean注解告诉Spring函数将返回一个对象,该对象需要注册为Spring应用上下文中的bean,该方法中包含了产生bean实例的逻辑

package com.seven.springTest.Configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import com.seven.springTest.service.MusicSource;
import com.seven.springTest.service.MediaPlayer;
import com.seven.springTest.service.impl.CDPlayer;
import com.seven.springTest.service.impl.CDSource;

@Configuration
public class MediePlayerConfig {

    @Bean   //该方法返回的MusicSource对象需要注册为Spring应用上下文中的bean
    public MusicSource cdsource(){
        return new CDSource();
    }

    @Bean  //该方法返回的MediaPlayer对象需要注册为Spring应用上下文中的bean
    public MediaPlayer cdplayer(){
        return new CDPlayer();
    }

}

MediePlayerConfig类中,我们只添加了@Configuration注解,之前的@ComponentScan注解移除了,没有配置启动Spring的组件扫描,另外接口的实现类也没有添加@Component注解,我们通过@Bean注解来告诉Spring哪些对象需要被注册为Spring应用上下文中的bean。cdsource()方法返回了一个MusicSource类型的实例对象CDSource,该对象被注册到Spring应用上下文,同样的cdplayer()方法返回了一个MediaPlayer类型的实例CDPlayer注册到Spring应用上下文中。下面我们来测试下

package com.seven.springTest.main;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.seven.springTest.Configuration.MediePlayerConfig;
import com.seven.springTest.Configuration.HelloWorldConfig;
import com.seven.springTest.service.MediaPlayer;

public class MediaPlayerTest {
    public static void main(String[] args) {
        //加载java配置类获取Spring应用上下文
        ApplicationContext ac = new AnnotationConfigApplicationContext(MediePlayerConfig.class);
        //获取播放器
        MediaPlayer player= ac.getBean(MediaPlayer.class);
        //播放
        player.play();
    }
}

我们在获取播放器bean的时候,其实获取到的就是MediePlayerConfig类中cdplayer()返回的对象CDPlayer,在CDPlayer中我们依赖MusicSource,通过@Autowired注解,Spring自动为该bean注入了对MusicSource的依赖,所以在测试代码中我们只是获取了MediaPlayer对象的实例player,至于player有哪些依赖,我们都不知道,都是由Spring容器来给我注入,这里只关心播放器player,这就是Spring给我们带来的便捷,我们不需要用代码去管理对象的依赖关系,对象所有依赖的资源都有Spring容器来为我们注入。

随着技术的发展,有一天光驱也可以插入U盘播放MP3音乐了,这个时候我们来实现一个MP3的音乐资源

package com.seven.springTest.service.impl;

import com.seven.springTest.service.MusicSource;

public class MP3Source implements MusicSource {

    private String title = "外婆";
    private String artist = "周杰伦";

    @Override
    public void play() {
        // TODO Auto-generated method stub
        System.out.println("MP3 Playing " + title + " by " + artist);
    }

}

在第一部分自动装配中,如果Spring发现了多个bean满足依赖关系,Spring就无法选择了,那么如果我们定义了MP3Source的实现,现在会不会也出现这样的情况呢?通过运行程序,我们发现没有产生任何影响,CDPlayer bean被注入的MusicSource依赖还是CDSource。这是因为我们在MediePlayerConfig中通过cdsource()告知了Spring产生bean的实现逻辑,那我们来修改下cdsource()

@Bean   //该方法返回的MusicSource对象需要注册为Spring应用上下文中的bean
public MusicSource cdsource(){
    //返回MP3Source实例
    return new MP3Source();
}

我们再运行下测试方法,发现输出内容变成了“==MP3 Playing 外婆 by 周杰伦==”,说明注入的依赖对象实现发生变化了,这是因为 cdsource()内实现的是返回MP3Source的实例。

同之前@Component一样,添加@Bean注解的方法返回的bean也会被默认分配一个ID,默认情况下和方法名相同,如cdsource()方法返回的bean的ID就为“cdsource”,我们也可以指定bean的ID,如下:

@Bean(name="myCdplayer")      //该方法返回的MediaPlayer对象需要注册为Spring应用上下文中的bean
public MediaPlayer cdplayer(){
    return new CDPlayer();
}

这样在获取bean的时候就可以通过ID来获取

public class MediaPlayerTest {
    public static void main(String[] args) {
        //加载java配置类获取Spring应用上下文
        ApplicationContext ac = new AnnotationConfigApplicationContext(MediePlayerConfig.class);
        //根据ID获取bean
        MediaPlayer player= (MediaPlayer) ac.getBean("myCdplayer");
        //播放
        player.play();
    }
}

上面的案例中CDPlayer bean它依赖了MusicSource的依赖,我们在CDPlayer类中通过@Autowired声明了CDPlayer需要的依赖,这里还是一种通过注解隐式的配置,下面我们来通过java配置类来实现。

如果是显式的配置,由于MediePlayerConfig中配置的bean都是通过方法返回的,所以需要在返回对象bean的方法里注入依赖:

@Bean(name="myCdplayer")  //该方法返回的MediaPlayer对象需要注册为Spring应用上下文中的bean
public MediaPlayer cdplayer(){
    return new CDPlayer(cdsource());   //通过对象的构造函数注入依赖
}

或者

@Bean(name="myCdplayer")  //该方法返回的MediaPlayer对象需要注册为Spring应用上下文中的bean
public MediaPlayer cdplayer(MusicSource musicSource){
    return new CDPlayer(musicSource);   //通过对象的构造函数注入依赖
}

通过上面2中方式配置,Spring都可以对CDPlayer中的MusicSource对象完成依赖注入,下面我们在定义一个bean配置

@Bean(name="myCdplayer")  //该方法返回的MediaPlayer对象需要注册为Spring应用上下文中的bean
public MediaPlayer cdplayer(){
    return new CDPlayer(cdsource());   //通过对象的构造函数注入依赖
}

@Bean(name="otherCdplayer")   //定义另外一个bean对象,
public MediaPlayer othercdplayer(){
    return new CDPlayer(cdsource());
}

MediaPlayer接口增加一个获取播放资源的方法

package com.seven.springTest.service;

public interface MediaPlayer {

    /**
    * 获取播放器加载的资源
    * @return MusicSource
    */
    MusicSource getResource();

    /**
     * 播放
     */
    void play();
}

解下列,我们修改下Test代码

package com.seven.springTest.main;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.seven.springTest.Configuration.MediePlayerConfig;
import com.seven.springTest.Configuration.HelloWorldConfig;
import com.seven.springTest.service.MediaPlayer;

public class MediaPlayerTest {
    public static void main(String[] args) {
        // 加载java配置类获取Spring应用上下文
        ApplicationContext ac = new AnnotationConfigApplicationContext(MediePlayerConfig.class);
        // 获取播放器
        MediaPlayer player = (MediaPlayer) ac.getBean("myCdplayer");
        MediaPlayer otherplayer = (MediaPlayer) ac.getBean("otherCdplayer");
        if (player.getResource().equals(otherplayer.getResource())) {
            System.out.println("true");
        }
        // 播放
        //player.play();
    }
}

运行后,我们发现输出“true”,这说明的什么情况呢,我们在cdplayer()和othercdplayer()方法中在调用CDPlayer(cdsource())构造时,通过cdsource()获取的音乐资源对象是相同的,在默认情况下,Spring中的bean都是单例的,Spring会拦截对cdsource()的调用,并确保返回的是Spring创建的bean,也就是Spring本身在第一次调用cdsource()所创建的bean。

时间: 2024-10-15 19:00:00

Spring学习系列(三) 通过Java代码装配Bean的相关文章

Spring装配之——JAVA代码装配Bean

首先创建几个普通的JAVA对象,用于测试JAVA代码装配bean的功能. 1 package soundsystemJava; 2 3 //作为接口 定义了CD播放器对一盘CD所能进行的操作 4 public interface CD { 5 void play(); 6 } 1 package soundsystemJava; 2 //接口的一个实现 3 public class CDTest1 implements CD { 4 5 private String title = "十一月的肖

2.2、通过Java代码装配bean

通过Java代码装配bean 例如,需要将第三方库的组件加载到你的应用中,此时无法给他的类上添加@Component和@Autowired注解,此时不能使用自动化装配了. 这种情况下,就必须使用显式装配的形式,可以选择Java代码装配或Xml装配 建议:显式配置是优先使用JavaConfig装配,因为他强大.类型安全且对重构友好:因为他和业务代码无关,应放到单独的包中 @Configuration 告诉Spring,这是一个Spring配置类,用来配置Spring应用上下文如何配置bean @B

Spring装配bean--02通过Java代码装配bean

Spring容器负责创建应用程序中的bean并通过DI来协调这些对象之间的关系 Spring提供了三种主要的装配机制: 在XML中进行显式配置 在Java中进行显式配置 隐式的bean发现机制和自动装配 2在Java中显式配置 尽管在很多场景下通过组件扫描和自动装配实现Spring的自动化装配是更为推荐的方式,但是当你要将第三方库中的组件装配到你的应用中,这时就必须显式的配置bean 显式配置包括:Java和XML,我更推荐使用Java类配置,就像上文中的JavaConfig那样 JavaCon

通过Java代码装配Bean

上面梳理了通过注解来隐式的完成了组件的扫描和自动装配,下面来学习下如何通过显式的配置的装配bean 二.通过Java类装配bean 在前面定义了HelloWorldConfig类,并使用@ComponentScan和@Configuration注解,@Configuration注解表明了这个类是一个java配置类,该类用在获取Spring应用上下文时,告诉Spring创建bean的细节,通过@ComponentScan,我们启用了Spring的自动组件扫描,现在就让我们来看如果通过java类来显

Sping实战之通过JAVA代码装配Bean

尽管在很多场景下通过组件扫描和自动装配实现Spring的自动化配置是更为推荐的方式,但有时候自动化配置的方案行不通,因此需要明确配置Spring.比如说,你想要将第三方库中的组件装配到你的应用中,在这种情况下,是没有办法在它的类上添加@Component和@Autowired注解的,因此就不能使用自动化装配的方案了. 在这种情况下,你必须要采用显式装配的方式.在进行显式配置的时候,有两种可选方案:Java和XML.在这节中,我们将会学习如何使用Java配置,接下来的一节中将会继续学习Spring

Spring学习系列之——第三章:Spring中Bean的配置(一)

Spring的配置形式有两种:基于XML配置和基于注解配置. Bean的配置方式有以下几种: 通过全类名,即通过反射的方式: 通过工厂方法,有静态工厂方法和实例工厂方法: 通过FactoryBean配置: 通过XML文件配置bean 本篇文章将按照下面的目录来说明基于XML的方式配置bean JavaBean的创建 通过XML配置的方式来配置bean XMLbean的配置: spring的依赖注入的方式 属性注入 构造器注入 工厂方法注入(很少使用) 测试方法 IoC容器的实例化: Applic

Spring Data 系列(三) Spring+JPA(spring-data-commons)

本章是Spring Data系列的第三篇.系列文章,重点不是讲解JPA语法,所以跑开了JPA的很多语法等,重点放在环境搭建,通过对比方式,快速体会Spring 对JPA的强大功能. 准备代码过程中,保持了每个例子的独立性,和简单性,准备的源码包,下载即可使用.如果,对JPA语法想深入研究的话,直接下载在此基础上进行测试. 前言 Spring Data 系列(一) 入门:简单介绍了原生态的SQL使用,以及JdbcTemplate的使用,在这里写SQL的活还需要自己准备. Spring Data 系

Spring Boot 使用Java代码创建Bean并注册到Spring中

从 Spring3.0 开始,增加了一种新的途经来配置Bean Definition,这就是通过 Java Code 配置 Bean Definition. 与Xml和Annotation两种配置方式不同点在于: 前两种Xml和Annotation的配置方式为预定义方式,即开发人员通过 XML 文件或者 Annotation 预定义配置 bean 的各种属性后,启动 Spring 容器,Spring 容器会首先解析这些配置属性,生成对应都?Bean Definition,装入到 DefaultL

六、Android学习笔记_JNI_c调用java代码

1.编写native方法(java2c)和非native方法(c2java): package com.example.provider; public class CallbackJava { // C调用java空方法 public void helloFromJava() { System.out.println("hello from java"); } // C调用java中的带两个int参数的方法 public int Add(int x, int y) { int res