Spring依赖注入详解

栏目: Java · 发布时间: 7年前

内容简介:Spring依赖注入详解

一、概述

Spring框架是以 简化Java EE应用程序的开发 为目标而创建的。Spring可以实现很多功能,但是这些功能的底层都依赖于它的两个核心特性,也就是依赖注入和面向切面编程。几乎Spring所做的任何事情都可以追溯到下述的一条或多条策略:

基于POJO的轻量级和最小侵入性编程;

通过依赖注入和面向接口实现松耦合;

基于切面和惯例进行声明式编程;

通过切面和模板减少样板式代码。 

Spring的三个基本愿景:

使用DI来实现低耦合

使用AOP切面实现高内聚

使用模板消除样板式代码,比如jdbcTemplate

二、Bean

容器是Spring框架的核心。Spring容器使用DI管理构成应用的组件(Bean),它会创建相互协作的组件之间的关联。毫无疑问,这些对象更简单干净,更易于理解和重用,更易于单元测试。

Spring为每个Bean定义了多种作用域,默认都是以单例的模式创建的:

单例(Singleton):在整个应用中,只创建bean的一个实例。

原型(Prototype):每次注入或者通过Spring应用上下文获取的时候,都会创建一个新的bean实例。

会话(Session):在Web应用中,为每个会话创建一个bean实例。

请求(Rquest):在Web应用中,为每个请求创建一个bean实例。

Bean的生命周期:

Spring依赖注入详解

Spring自带了多种类型的上下文(适用于在普通类中利用Spring的上下文加载需要的Bean):

AnnotationConfigApplicationContext:从一个或者多个的 Java 配置类中加载Spring的应用上下文

Spring依赖注入详解
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(JavaConfig.class);

AnnotationConfigWebApplicationContext:从一个或多个基于Java的配置类中加载Spring Web应用上下文。

ClassPathXmlApplicationContext:从类路径下的一个或多个XML配置文件中加载上下文定义,把应用上下文的定义文件作为类资源。

Spring依赖注入详解
ApplicationContext applicationContext= new ClassPathXmlApplicationContext("applicationContext.xml");

FileSystemXmlapplicationcontext:从文件系统下的一个或多个XML配置文件中加载上下文定义。

XmlWebApplicationContext:从Web应用下的一个或多个XML配置文件中加载上下文定义。

三、依赖注入

1、@Component表明该类会作为组件类,并告知Spring 要为这个类创建bean(这个bean的ID默认取名类名的首字母小写)。不过组件扫描默认是不启用的。我们还需要显示配置一下Spring,从而命令他去寻找带有@Component(类似的还有 @Repository @service @controller )注解的类,并为他创建bean。有三种方式来配置Spring创建Bena:

* 自动化装配的方式:1、建一个配置类。 @Configuration 表明这个类是一个配置类 加上 @ComponentScan (basePackages={"包名1","包名2"} 或者 basePackageClasses={包1的某个Class,包2的某个Class}) 会扫描和配置类相同的包,以及这个包下的所有子包。

2、Spring XML配置方式: <context:component-scan base-package=""/>

在JavaConfig中进行显示配置(适用于第三方的类库组件装配到自己应用中)  

Spring依赖注入详解
@Configuration
public class JavaConfig {



    @Bean(name = "base64Util")
    public Base64Util getBase64Util(){
        return new Base64Util();
    }

    @Bean(name = "base64UtilExpand") //这种显示配置默认的Bean名是方法名。所以最好显示配置一下
    public Base64UtilExpand getBase64UtilExpand(){
        //对于这种创建的bean需要引用其他的bean。Spring是这样处理的:当引用到还没创建的bean的时候,Spring会拦截下这个引用,等到引用的bean的创建完成。已保证Spring bean的单例模式.
        return new Base64UtilExpand(getBase64Util());
    }
    
    @Bean(name = "base64UtilExpand")
    public Base64UtilExpand getBase64UtilExpand(Base64Util base64Util){
        return new Base64UtilExpand(base64Util);
    }
}

在XML中进行显示配置,最古老的方式,一般很少用,有两种方式注入,构造器注入和set注入:

Spring依赖注入详解
<!--构造器注入-->
    <bean id="cDPlayer" class="com.CDPlayer">
        <constructor-arg ref="compactDisc">
    </bean>
    <bean id="cDPlayer" class="com.CDPlayer">
        <constructor-arg value="compactDisc">
    </bean>
    <bean id="cDPlayer" class="com.CDPlayer">
        <constructor-arg>
            <list>
                <value></value>
            </list>
        </constructor-arg>
    </bean>

    <!--setter注入-->
    <bean id="cDPlayer" class="com.CDPlayer">
        <property name="compactDisc" ref="compactDisc">
    </bean>
    <bean id="cDPlayer" class="com.CDPlayer">
        <property name="compactDisc" value="compactDisc"><!--装配字面量:-->
    </bean>
    装配集合
    <bean id="cDPlayer" class="com.CDPlayer">
        <property name="compactDisc" value="compactDisc">
        <property name="">
            <list>
                <value></value><!--装配集合-->
            </list>
        </property>
    </bean>

2、@scope指定bean创建时的作用域,Spring默认创建单例模式的bean。但也有特殊的情况,这里需要说明的是如果某个类注入了Session 和 Request 作用域的Bean,因为这个Bean是在用户请求的时候产生的,在Spring 运行起来的时候并不存在。这里Spring是这样处理的:注入给对应Bean的一个代理,而当用户请求产生session 或者 request 作用域Bean的时候,由这个代理连接到相应的Bean处理请求...

Spring依赖注入详解

原型:@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

会话:(接口)@Scope(value = WebApplicationContext.SCOPE_SESSION,proxyMode = ScopedProxyMode.INTERFACES)

(具体类)@Scope(value = WebApplicationContext.SCOPE_SESSION,proxyMode = ScopedProxyMode.TARGET_CLASS)

当然也可以在XML中配置:

Spring依赖注入详解
<bean id="shoppingCart2" class="com.entity.ShoppingCart2" scope="session">
        <aop:scoped-proxy proxy-target-class="false"/>
    </bean>

3、限定符(用的较少)

@Profile决定哪些bean可以被激活。需要注意的是没有指定profile的bean始终都会被创建,与激活哪个profile没有关系。

 @Conditional中给定了一个Class,这个Class 实现了Codition 接口的matches 方法,该方法返回true 则生成bean,否则不生成。

@primary常见的情况是一个接口仅有一个实现类,所以使用@Autowire的后,Spring可以走到对应的实现类。如果一个接口有多个实现类呢?@Component 和 @primary 同时使用,标注哪个实现类优先被使用。

 @Qualifier使用@primary 仍然无法保证哪个bean被选择,因为可以在多个实现类上使用@primary。所以可以在实现类用@Qualifter("bean")名指定bean的名字。并在@Autowire 注入接口的时候是使用Qualifier 指定实现类的bean名。当然,也可以用@Resource(name=" ")指定类的名称。

4、读取 properties 文件

(1) @PropertySource会引用一个类路径上的properties的文件,并利用Environment类获取properties的变量值。例如:@PropertySource("classpath:mongo.properties")

Spring依赖注入详解
@Configuration
@PropertySource("classpath:mongo.properties")
public class JavaConfig {
    
    @Bean(name = "mongoUtil")
    public MongoUtil getMongoUtil(Environment env){
        return new MongoUtil(env.getProperty("mongo.host"),
                env.getProperty("mongo.port"),
                env.getProperty("mongo.database"),
                env.getProperty("mongo.username"),
                env.getProperty("mongo.password"));
    }
}

Spring依赖注入详解

(2) 占位符

     Spring 中占位符的形式是使用${}的方式。在代码文件中我们可以使用 @Value 注解将配置文件的值注入到变量中。为了使用占位符,我们必须配置一个PropertySourcesPlaceholderConfigurer 的类,已生成相关的bean,或者通过XML配置让Spring为我们自动生成:

Spring依赖注入详解
@Configuration
@PropertySource("classpath:mongo.properties")
public class JavaConfig {
    
    @Bean(name = "propertySourcesPlaceholderConfigurer")
    public PropertySourcesPlaceholderConfigurer getPropertySourcesPlaceholderConfigurer(){
        return new PropertySourcesPlaceholderConfigurer();
    }
}

或者:

Spring依赖注入详解
<!--提供读取配置文件可以使用Spring占位符${}-->
    <context:property-placeholder location="classpath:mongo.properties" file-encoding="utf-8" />

用法如下:

Spring依赖注入详解
@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration(classes = JavaConfig.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class Test06 {

    @Value("${mongo.host}")
    private String host;

    @Test
    public void test06(){
        System.out.println(host);
    }
}

四、Expression Language

Spring Expression Language,简称SpEL,是一种非常灵活的表达式语言,拥有很多特性,包括:

使用bean的ID来引用bean;

调用方法和访问对象的属性;

对值进行算术、关系和逻辑运算;

正则表达式匹配;

集合操作。

SpEL 采用#{}的形式:

1、代表字面值:#{3.14} #{'Hello'} #{false}

2、引用bean、属性、方法 #{bean} #{bean.artist} #{bean.toUpperCase()} #{bean?.toUpperCase()}(表示如果bean为null 就返回null,不调用方法)

3、引用某个类 #{T{java.lang.Math}.PI}

4、三元表达式 #{bean.score > 1000 ? "win":"los"} 判空 #{bean.score ?: "win"}

5、正则表达式 #{bean.email matches '表达式'}

6、计算集合 #{bean.song[4].title}

查询运算符(.?)  #{bean.songs.?[artist eq 'hello']}

匹配第一个 (.^)  #{bean.songs.^[artist eq 'hello']}

匹配最后一个 (.$) : 

#{bean.songs.$[artist eq 'hello']}

      投影运算符 (.!)  #{bean.songs.![title]}

Spring依赖注入详解
<bean id="carl" class="com.springinaction.springidol.Instrumentalist">
    <property name="song" value="#{kenny.song}" />
</bean>
Spring依赖注入详解
public static class FieldValueTestBean {
    @Value("#{ systemProperties['user.region'] }")
    private String defaultLocale;
    public void setDefaultLocale(String defaultLocale) {
        this.defaultLocale = defaultLocale;
    }
    public String getDefaultLocale() {
        return this.defaultLocale;
    }
}

Spring为SpEL创造了两种特殊的选择属性方式:systemEnvironment和systemProperties.

systemEnvironment包含了应用程序所在机器上的所有环境变量。 

systemProperties包含了java应用程序启动时所设置的所有属性。

Spring依赖注入详解

Spring依赖注入详解

五、JUnit 测试

@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration(classes = JavaConfig.class) 加载配置类
@ContextConfiguration(locations = "classpath:applicationContext.xml") //加载配置文件
public class Test02 {

    @Resource(name = "iceCream")
    private Dessert dessert;

    @Test
    public void test02(){
        dessert.sys();
    }

}

本文永久更新链接地址 http://www.linuxidc.com/Linux/2017-12/149784.htm


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Head First JavaScript Programming

Head First JavaScript Programming

Eric T. Freeman、Elisabeth Robson / O'Reilly Media / 2014-4-10 / USD 49.99

This brain-friendly guide teaches you everything from JavaScript language fundamentals to advanced topics, including objects, functions, and the browser’s document object model. You won’t just be read......一起来看看 《Head First JavaScript Programming》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具