再学习之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的生命周期:
Bean实例生命周期的执行过程如下:
Spring对bean进行实例化,默认bean是单例;
Spring对bean进行依赖注入;
如果bean实现了BeanNameAware接口,spring将bean的id传给setBeanName()方法;
如果bean实现了BeanFactoryAware接口,spring将调用setBeanFactory方法,将BeanFactory实例传进来;
如果bean实现了ApplicationContextAware接口,它的setApplicationContext()方法将被调用,将应用上下文的引用传入到bean中;
如果bean实现了BeanPostProcessor接口,它的postProcessBeforeInitialization方法将被调用;
如果bean实现了InitializingBean接口,spring将调用它的afterPropertiesSet接口方法,类似的如果bean使用了init-method属性声明了初始化方法,该方法也会被调用;
如果bean实现了BeanPostProcessor接口,它的postProcessAfterInitialization接口方法将被调用;
此时bean已经准备就绪,可以被应用程序使用了,他们将一直驻留在应用上下文中,直到该应用上下文被销毁;
若bean实现了DisposableBean接口,spring将调用它的distroy()接口方法。同样的,如果bean使用了destroy-method属性声明了销毁方法,则该方法被调用;
Spring自带了多种类型的上下文(适用于在普通类中利用Spring的上下文加载需要的Bean):
AnnotationConfigApplicationContext:从一个或者多个的Java配置类中加载Spring的应用上下文
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(JavaConfig.class);
AnnotationConfigWebApplicationContext:从一个或多个基于Java的配置类中加载Spring Web应用上下文。
ClassPathXmlApplicationContext:从类路径下的一个或多个XML配置文件中加载上下文定义,把应用上下文的定义文件作为类资源。
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中进行显示配置(适用于第三方的类库组件装配到自己应用中)
@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注入:
<!--构造器注入-->
<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处理请求...
单例(一个应用创建一个实例):@Scope(value=ConfigurableBeanFactory.SCOPE_SINGLETON)
请求(一个请求创建一个实例):@Scope(value=WebApplicationContext.SCOPE_REQUEST,proxyMode = ScopedProxyMode.INTERFACES)
原型(一次注入创建一个实例):@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
会话(一次会话创建一个实例):
(接口)@Scope(value = WebApplicationContext.SCOPE_SESSION,proxyMode = ScopedProxyMode.INTERFACES)
(具体类)@Scope(value = WebApplicationContext.SCOPE_SESSION,proxyMode = ScopedProxyMode.TARGET_CLASS)
全局会话(全局会话创建一个实例):@Scope(value=WebApplicationContext.SCOPE_GLOBAL_SESSION)
当然也可以在XML中配置:
<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")
@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"));
}
}
(2) 占位符
Spring 中占位符的形式是使用${}的方式。在代码文件中我们可以使用@Value注解将配置文件的值注入到变量中。为了使用占位符,我们必须配置一个PropertySourcesPlaceholderConfigurer 的类,已生成相关的bean,或者通过XML配置让Spring为我们自动生成:
@Configuration
@PropertySource("classpath:mongo.properties")
public class JavaConfig { @Bean(name = "propertySourcesPlaceholderConfigurer")
public PropertySourcesPlaceholderConfigurer getPropertySourcesPlaceholderConfigurer(){
return new PropertySourcesPlaceholderConfigurer();
}
}
或者:
<!--提供读取配置文件可以使用Spring占位符${}-->
<context:property-placeholder location="classpath:mongo.properties" file-encoding="utf-8" />
用法如下:
@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]}
<bean id="carl" class="com.springinaction.springidol.Instrumentalist">
<property name="song" value="#{kenny.song}" />
</bean>
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应用程序启动时所设置的所有属性。
五、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();
} }
再学习之Spring(依赖注入)的更多相关文章
- Spring学习笔记——Spring依赖注入原理分析
我们知道Spring的依赖注入有四种方式,各自是get/set方法注入.构造器注入.静态工厂方法注入.实例工厂方法注入 以下我们先分析下这几种注入方式 1.get/set方法注入 public cla ...
- [学习笔记]Spring依赖注入
依赖: 典型的企业应用程序不可能由单个对象(在spring中,也可称之bean)组成,再简单的应用也是由几个对象相互配合工作的,这一章主要介绍bean的定义以及bean之间的相互协作. 依赖注入: s ...
- Spring依赖注入原理分析
在分析原理之前我们先回顾下依赖注入的概念: 我们常提起的依赖注入(Dependency Injection)和控制反转(Inversion of Control)是同一个概念.具体含义是:当某个角色( ...
- Spring依赖注入(IOC)那些事
小菜使用Spring有几个月了,但是对于它的内部原理,却是一头雾水,这次借着工作中遇到的一个小问题,来总结一下Spring. Spring依赖注入的思想,就是把对象交由Spring容器管理,使用者只需 ...
- Spring依赖注入三种方式详解
在讲解Spring依赖注入之前的准备工作: 下载包含Spring的工具jar包的压缩包 解压缩下载下来的Spring压缩包文件 解压缩之后我们会看到libs文件夹下有许多jar包,而我们只需要其中的c ...
- Spring依赖注入:注解注入总结
更多11 spring 依赖注入 注解 java 注解注入顾名思义就是通过注解来实现注入,Spring和注入相关的常见注解有Autowired.Resource.Qualifier.S ...
- Spring依赖注入 --- 简单使用说明
Spring依赖注入 --- 简单使用说明 本文将对spring依赖注入的使用做简单的说明,enjoy your time! 1.使用Spring提供的依赖注入 对spring依赖注入的实现方法感兴趣 ...
- Java Web系列:Spring依赖注入基础
一.Spring简介 1.Spring简化Java开发 Spring Framework是一个应用框架,框架一般是半成品,我们在框架的基础上可以不用每个项目自己实现架构.基础设施和常用功能性组件,而是 ...
- 二十7天 春雨滋润着无形 —Spring依赖注入
6月11日,明确."夏条绿已密,朱萼缀明鲜.炎炎日正午,灼灼火俱燃." IT人习惯把详细的事物加工成的形状一致的类.正是这种一致,加上合适的规范.才干彰显对象筋道的牙感和bean清 ...
随机推荐
- Hadoop(十七)之MapReduce作业配置与Mapper和Reducer类
前言 前面一篇博文写的是Combiner优化MapReduce执行,也就是使用Combiner在map端执行减少reduce端的计算量. 一.作业的默认配置 MapReduce程序的默认配置 1)概述 ...
- LeetCode 292. Nim Game (取物游戏)
You are playing the following Nim Game with your friend: There is a heap of stones on the table, eac ...
- struts2类型转换相关问题
一.类型转化错误时,如何处理? 若Action类没有实现ValidationAware接口,在类型转化错误时,struts2会继续调用action方法,将该属性值置为默认值,不报错. 若Action类 ...
- Apache和Tomcat整合(一个Apache 不同域名处理多个不同业务)
一.简介 在项目中,几乎任何一个项目都包括静态资源和动态请求两大部分.特别对于门户网站这样的项目,静态内容资源会更多,我们使用一般的 Tomcat 部署时,Tomcat 对静态资源的处理能力比较慢,至 ...
- 关于C++中vector和set使用sort方法进行排序
C++中vector和set都是非常方便的容器, sort方法是algorithm头文件里的一个标准函数,能进行高效的排序,默认是按元素从小到大排序 将sort方法用到vector和set中能实现多种 ...
- cross-document message 跨文档通信 HTML5
跨域通信HTML5提供了XDM(cross-document message)安全简单接口: 核心是 postMessage()方法,用来向另一个地址传送信息: var iframeWindow ...
- Hibernate开发文档
hibernate配置 映射约束文件 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3. ...
- 学Java的前景与就业,资深程序员教你怎么开始学Java!
IT行业一直是就业的热门岗位,程序员这个职业稳定性和收入比都有着不错的前景,那么学Java的前景和就业是什么样的呢?随着入行Java的准程序员越来越多,各种学习Java的流派也层出不穷!其实在编程的世 ...
- elastic-search单机部署以及中文分词IKAnalyzer安装
前提条件 elasticsearch使用版本5.6.3,需要jdk版本1.8,低于该版本不能使用 下载 https://artifacts.elastic.co/downloads/elasticse ...
- 【基础】Attribute的妙用
一.何为Attribute 下面是微软官方对Attribute的解释: 公共语言运行时允许你添加类似关键字的描述声明,叫做Attributes,它对程序中的元素进行标注,如类型.字段.方法和属性等.A ...