spring 4.0.2.RELEASE 自动化装配

简介: spring 4.0.2.RELEASE 自动化装配

spring 4.0.2.RELEASE 自动化装配

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

组件扫描(component scanning):Spring会自动扫描上下文中所创建的bean

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

创建可被发现的bean

音乐专辑为例,一张音乐专辑(CD)需要一个CD播放器才能放出音乐,在这期间需要将CD插入(注入)CD播放器中才能达到我们想要的效果,而这个CD与CD播放器之间的依赖关系能够生动的向我们阐述DI是如何运行的。

首先我们要定义一个CD的概念:创建接口类Disc

package demo;

public interface IDisk {
    public void play();
}

根据这个接口类声明一个带有@Component注解的实现类fristAlbum

package demo.impl;

import demo.IDisk;
import org.springframework.stereotype.Component;

@Component
public class firstAlbum implements IDisk {
    private static String songTitle = "first song";
    private static String artist = "carl";
    public void play() {
        System.out.println("Playing " + songTitle + "by " + artist);
    }
}

这里的@Component注解是标识这个类为组件类并告知Spring为其创建bean对象。与以往不同的是不需要再xml中显示的配置bean,Spring会根据你所做的标识来完成配置工作。

Spring会根据注解来扫描指定包中需要创建bean对象的类,但Spring的组件扫描默认是不启动的,所以我们还需要进行一些配置,来启用组件扫描。

启用组件扫描

启用组件扫描有两种方式,一种是以java注解的形式启用,另外一种则是在xml中配置启用

java注解启用
package demo.impl;

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

@Configuration
@ComponentScan
public class CDPlayerConfig {
       
}
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">

    <context:component-scan base-package="demo.impl"/>

</beans>

在用两种配置方法配置之后,我们来测试一下Spring是否能够扫描到注解配置过得实现类,这里编写测试用例来测试一下。

package demo.demoTest;

import demo.IDisk;
import demo.impl.CDPlayerConfig;
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;

@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration(locations = "classpath:applicationContext.xml")
@ContextConfiguration(classes = CDPlayerConfig.class)
public class demoTest {

    @Autowired
    private IDisk disk;

    @Test
    public void run(){
        disk.play();
    }
}

注释掉的一行就是测试xml配置的注解,@Autowired注解则是让Spring创建的bean注入到disk对象中,由此来验证是否扫描成功。(这里使用了spring-test包,maven加一下依赖就好了)

为被扫描的bean命名

我们假设一种情况:如果有两个实体类实现了同一个接口类,那么在依赖注入的时候会出现冲突因为@Autowired是根据类型注入的,这时候有两个相同类型的bean要注入那必然会出现冲突。这里就需要对bean进行命名,我们创建一个新的实体类secondAlbum并依旧使用@Conponent 注解,只是这回要为它加上参数

package demo.impl;

import demo.IDisk;
import org.springframework.stereotype.Component;

@Component("secondAlbum")
public class secondAlbum implements IDisk {
    private static String title = "second song";
    private static String artist = "carl";
    public void play() {
        System.out.println("Playing "+ title + " by " + artist);
    }
}

这样就可以在注入的时候根据名称判断需要注入的是哪个bean,对测试用例进行以下修改

public class demoTest {

    @Autowired
    @Qualifier("secondAlbum")
    private IDisk disk;

    @Test
    public void run(){
        disk.play();
    }
}

或者

public class demoTest {

    @Resource(name = "secondAlbum")
    private IDisk disk;

    @Test
    public void run(){
        disk.play();
    }
}

这里要提一句的是,@Autowired要和@Qualifier一起用才能达到ByName的目的,因为Autowired是负责ByType注入的,然后Qualifier再根据Name选择注入哪个Bean,从而实现对应Name注入需要的Bean。

另一种方法使用了@Resource注解,这个注解用于将一个_named bean_注入。当然,可以同时限定_name_和_type_来保证注入的bean是需要的bean。

设置多个扫描包或指定扫描类

使用@ComponentScan注解默认是扫描当前包下的所有组件,当然按照需要也可以设置多个扫描包或者扫描类,@ComponentScan注解提供了两个参数,分别是__basePackages__和__basePackageClasses__,前者需要字符串类型的数组作为参数,后者测需要class类型的数组

package demo.impl;

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

@Configuration
@ComponentScan(basePackages = {"demo.impl","demo.demoTest"})
//@ComponentScan(basePackageClasses = {demo.impl.firstAlbum.class})
public class CDPlayerConfig {

}

通过为bean添加@Component注解实现自动注入

创建__MediaPlayer__接口类

package demo;

public interface MediaPlayer {

    public void play();

}

创建__CDPlayer__类并实现MediaPlayer接口

package demo.impl;

import demo.IDisk;
import demo.MediaPlayer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
public class CDPlayer implements MediaPlayer {

    @Autowired
    @Qualifier("secondAlbum")
    private IDisk disk;

    public void play() {
        disk.play();
    }
}

__@Autowired__注解同样可以作用于set方法和构造方法上

    //构造方法使用@Autowired
    @Autowired
    public CDPlayer(@Qualifier("firstAlbum")IDisk disk){
        this.disk = disk;
    }
    //set方法使用Autowired
    @Autowired
    @Qualifier("firstAlbum")
    private void setDisk(IDisk disk){
        this.disk = disk;
    }

这里注意,@Resource不适用于构造方法和set方法。

测试自动化装配

package demo.demoTest;

import demo.IDisk;
import demo.MediaPlayer;
import demo.impl.CDPlayerConfig;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;

@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration(locations = "classpath:applicationContext.xml")
@ContextConfiguration(classes = CDPlayerConfig.class)
public class demoTest {


    @Autowired
    private MediaPlayer mediaPlayer;

    @Test
    public void run(){
        mediaPlayer.play();
    }
}

Done!

目录
相关文章
|
3月前
|
Java Spring 容器
在 Spring Boot 中,条件装配(Conditional Configuration)和条件注解(Conditional Annotations)
在 Spring Boot 中,条件装配(Conditional Configuration)和条件注解(Conditional Annotations)
47 1
|
4月前
|
Java 关系型数据库 MySQL
高级对象装配:解析Spring创建复杂对象的秘诀
高级对象装配:解析Spring创建复杂对象的秘诀
46 0
高级对象装配:解析Spring创建复杂对象的秘诀
|
4月前
|
Java API Spring
|
XML Java 数据格式
Spring依赖注入、对象装配
在这篇博客中,我们学习到了spring依赖注入的三种常见的方式,并且了解了它们的优缺点,还了解了依赖注入的两个重要的关键字:@Autowired、@Resource,并了解了两者的区别。还知道了如何解决同一类型Bean注入的报错问题和了解了软件设计中的单一设计原则。
124 0
|
安全 Java Maven
徒手撸一个 Spring Boot 中的 Starter ,解密自动化配置黑魔法!(一)
徒手撸一个 Spring Boot 中的 Starter ,解密自动化配置黑魔法!
|
Java 数据库连接 测试技术
Spring高手之路9——掌握Spring条件装配的秘密武器
在Spring框架中,条件装配是一个强大的功能,可以帮助我们更好地管理和控制Bean的创建过程。本文详细解释了如何使用Spring的@Profile和@Conditional注解实现条件装配,通过具体的示例可以更好地理解这两个注解的用法和适用场景。深入研究这些注解,可以帮助提升Spring应用开发的技能,更好地掌握Spring框架。
153 0
Spring高手之路9——掌握Spring条件装配的秘密武器
|
开发框架 SpringCloudAlibaba Java
Spring注解装配:@Autowired和@Resource使用及原理详解
`@Resource`和`@Autowired`都是实现bean的注入,在日常开发中使用非常频繁,但是使用体验不太一样,笔者喜欢用`@Resource`,因为在使用`@Autowired`时IDEA会出现一些警告爆红提示
306 0
Spring注解装配:@Autowired和@Resource使用及原理详解
|
XML Java 测试技术
Spring高手之路8——Spring Bean模块装配的艺术:@Import详解
本文将带你深入探索Spring框架的装配机制,以及它如何使你的代码更具模块化和灵活性。我们首先介绍Spring手动装配的基础知识,然后进一步解析@Import注解在模块装配中的关键角色。文章涵盖从导入普通类、配置类,到使用ImportSelector和ImportBeanDefinitionRegistrar进行动态和选择性装配等多个层次,旨在帮助读者全面理解和掌握Spring的装配技术。
274 0
Spring高手之路8——Spring Bean模块装配的艺术:@Import详解
|
Java 测试技术 数据库连接
徒手撸一个 Spring Boot 中的 Starter ,解密自动化配置黑魔法!(二)
徒手撸一个 Spring Boot 中的 Starter ,解密自动化配置黑魔法!
|
XML Java 数据格式
Spring 的自动装配?有哪些方式?
Spring 的自动装配?有哪些方式?
112 0