Spring依赖注入bean

Spring依赖注入bean

介绍

Spring是一个开源框架,目的是简化Java开发,具备两大核心特性: 依赖注入(dependency injection, DI)和切面编程(aspect-oriented programming,AOP)。

依赖注入

依赖注入使得对象之间的耦合性降低, 基于Java中的反射机制实现。

Spring对于bean的装配提供了3种主要的装配机制:

  • XML配置
  • Java代码配置
  • 自动发现和自动装配

3种机制可单独使用一种,也可配合使用。本文先介绍自动发现和自动装配实现bean注入。介绍之前先引入spring依赖,以gradle为例

// build.gradle文件
dependencies {
    compile('org.springframework:spring-context')
    compile('org.springframework:spring-core')
    compile('org.springframework:spring-test')
}

机制1-自动装配

构造bean

为实现bean的装配,我们先实现一个bean,与普通类不同之处在于,用到@Component注解。如下示例是字符串的全半角转换。

package com.notepad.spring;

import org.springframework.stereotype.Component;

/**
 * Description:  字符串处理函数
 * <p>
 * Create:       2018/6/17 18:55
 *
 * @author Yang Meng(eyangmeng@163.com)
 */

@Component
public class StringProcess {

    /**
     * 字符串的全角转半角
     *
     * @param content 字符串
     * @return 半角字符串
     */
    public String stringQ2B(String content) {
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < content.length(); i++) {
            int asciiCode = (int) content.charAt(i);
            if (asciiCode >= 65281 && asciiCode <= 65374) {
                asciiCode -= 65248;
            } else if (asciiCode == 12288) {
                asciiCode = 32;
            }
            stringBuilder.append((char) asciiCode);
        }
        return stringBuilder.toString();
    }

    /**
     * 字符串半角转全角
     *
     * @param content 字符串
     * @return 全角字符串
     */
    public String stringB2Q(String content) {
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < content.length(); i++) {
            int asciiCode = (int) content.charAt(i);
            if (asciiCode >= 33 && asciiCode <= 126) {
                asciiCode += 65248;
            } else if (asciiCode == 32) {
                asciiCode = 12288;
            }
            stringBuilder.append((char) asciiCode);
        }
        return stringBuilder.toString();
    }
}

Java 配置类

构造Java配置类, 利用自动发现进行bean的扫描, 用到注解 @Configuration@ComponentScan

package com.notepad.spring;

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

/**
 * Description:  Spring Config配置(Java8)
 * <p>
 * Create:       2018/6/17 18:39
 *
 * @author Yang Meng(eyangmeng@163.com)
 */

@Configuration
@ComponentScan(basePackages = "com.notepad")
public class SpringConfig {
}

bean装配验证

构造单测验证bean是否可以正常装配和使用。利用@RunWith@ContextConfiguration来自动创建Spring上下文以及加载Java配置类,通过@Autowired注解实现bean的装配。

package com.notepad.spring;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import static org.junit.Assert.*;

/**
 * Description: Bean测试
 * <p>
 * Create:       2018/6/17 19:26
 *
 * @author Yang Meng(eyangmeng@163.com)
 */

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = StringProcess.class)
public class StringProcessTest {

    @Autowired
    private StringProcess stringProcess;

    @Test
    public void stringQ2B() {
        String content = "2018年世界杯开幕了。";
        System.out.println(stringProcess.stringQ2B(content));
    }

    @Test
    public void stringB2Q() {
        String content = "2018年世界杯。";
        System.out.println(stringProcess.stringB2Q(content));
    }
}

Main方法使用

利用SpringJUnit4ClassRunner可以完成单测, 但是如何Main方法中要使用该bean还需要用到AnnotationConfigApplicationContext来加载Spring上下文,示例如下:

package com.notepad.spring;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;


/**
 * Description:  Main方法中实用bean(Java8)
 * <p>
 * Create:       2018/6/17 23:14
 *
 * @author Yang Meng(eyangmeng@163.com)
 */
public class SpringMain {

    public static void main(String [] args) {
        StringProcess process = getStringProcess();
        if (process == null) {
            LOG.error("Can not create bean: StringProcess");
            return;
        }

        String content = "北京时间23点整。";
        System.out.println(process.stringQ2B(content));
    }

    /**
     * 通过上下文加载获取bean
     *
     * @return StringProcess
     */
    private static StringProcess getStringProcess() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        return context.getBean(StringProcess.class);
    }

    private final static Logger LOG = LoggerFactory.getLogger(SpringMain.class);
}

机制2-Java代码配置

不同于自动装配和自动发现, 利用Java代码实现bean的注入, 构造方式于普通类的构造无差别。

构造bean

对于自己构造的类, 我们可以为对象添加@Component注解, 但是对于三方包我们无法修改。仍以字符串串的全半角转换类为例。

Java configure 类

利用Java代码实现bean的装配, 构造Java configure来整理需要用到的bean,用到注解 @Configuration@Bean

@Bean注解显示的构造bean。

package com.notepad.spring;

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

/**
 * Description:  Spring Config配置(Java8)
 * <p>
 * Create:       2018/6/17 18:39
 *
 * @author Yang Meng(eyangmeng@163.com)
 */

@Configuration
public class SpringConfig {

    @Bean
    public StringProcess getStringProcess() {
        return new StringProcess();
    }
}

bean装配验证和Main方法使用

测试和使用方式同自动装配相同。

机制3-XML配置

利用XML配置文件实现bean的注入,也是最常用的一种方式。

构造bean

仍以字符串串的全半角转换类为例。无@Component注解。

XML配置

利用 实现定义, id为bean的名称且唯一, class指定具体的类

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--字符串处理-->
    <bean id="stringProcess" class="com.notepad.spring.StringProcess"/>
</beans>

Main方法使用

不同于Java配置的方法,利用XML配置需用到ClassPathXmlApplicationContext从XML中加载上下文。

package com.notepad.spring;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Description:  Main方法中实用bean(Java8)
 * <p>
 * Create:       2018/6/17 23:14
 *
 * @author Yang Meng(eyangmeng@163.com)
 */
public class SpringMain {

    public static void main(String [] args) {
        StringProcess process = getStringProcess();
        if (process == null) {
            LOG.error("Can not create bean: StringProcess");
            return;
        }

        String content = "北京时间23点整。";
        System.out.println(process.stringQ2B(content));
    }

    /**
     * 通过XML配置文件中加载上下文
     * @return StringProcess
     */
    private static StringProcess getStringProcess() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("answerbean-config.xml");
        return context.getBean(StringProcess.class);
    }

    private final static Logger LOG = LoggerFactory.getLogger(SpringMain.class);
}

总结

  1. @Component注解在普通类上声明bean
  2. @Configuration注解声明Java配置类, @ComponentScan实现自动扫描, @Bean注解声明具体bean实现细节
  3. @RunWith和@ContextConfiguration注解使用单测
  4. AnnotationConfigApplicationContext实现Main方法中加载利用Java配置类加载上下文
  5. ClassPathXmlApplicationContext实现XML加载上下文

后续问题

  1. Java配置类与XML配置相互配合
  2. Bean重名问题
  3. 类之外属性的注入
  4. 利用properties文件实现具体值注入等等

Github代码

https://github.com/yangbigmeng/notepad

参考

  1. Spring 实战(第四版) 第二章, 第三章

注: 本文介绍的均是Spring加载Bean的最基本的方法, bean的加载还设置多种类型, 如类的属性,方法,具体的值等,掌握bean注入的最好方法是根据参考文献了解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值