学习Spring——依赖注入
前言:
又开始动笔开了“学习Spring”系列的头……
其实一开始写“学习SpringMVC”的几篇文章是出于想系统的了解下Spring以及SpringMVC,因为平时在公司中虽然每天都在使用Spring相关的框架或者其他,但是绝大部分都是已经写好配置文件,做好相关配置,而我们能做的就是写一些与业务逻辑有关的Controller层面或者Service层面的代码。毕竟所做的产品成熟了,或者说框架越来越成熟了,我们对于底层原理的东西关注的就少了,认识也浅了。
个人感觉,颇具讽刺意味的是,“SpringMVC”系列的HelloWorld篇发出去后,每日阅读量出现了比以外任何一篇都要快的尴尬式增长,如今已经成为我第一篇超过5位数阅读量的文章,汗-_-!
本来只是想在了解了SpringMVC的套路后,稍稍的看下佟刚老师的Spring视频就算了。可是后来有网友问SpringMVC系列是否还有后续,我想了一下,那如果有的话可能就是Spring基础相关了吧;而且,有些东西只是抱着看一看的心态,最后得到的也就是看一看的反馈,一个小时又或是一天之后就完全忘得一干二净了。所以,算是一份笔记吧,这里开了个头。
通过之前SpringMVC的学习,似乎在某些瞬间,我似乎看到了一些与自己项目中似曾相识的套路,只是之前因为项目过大,或者自己做的只是一些细微的调整,很难发现项目的大森林全貌。学习Spring的时候,我也希望能够重现类似的桥段,这样的学习就是有回报的,值得的。
毫无意外可言,第一篇讲的还是HelloWorld(主要是依赖注入的特性)。
Spring
Spring 是一个开源框架。
Spring 是一个 IOC(DI) 和 AOP 容器框架(Spring的两大法宝)。
Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性的角度而言,绝大部分Java应用都可以从Spring中受益(总而言之,Spring就是很腻害)。
官网:https://spring.io/
HelloWorld实例对比
首先,需要新建一个Java Project,新建完成目录结构如下:
如你所见,这里还要一些需要用到的jar。
没有使用Spring的那一套
不可否认,在Spring没有横空出世的时候,太阳依旧是东起西落,地球如斯旋转。大概是这个样子:
新建HelloWorld类
public class HelloWorld { private String name; public HelloWorld() {
System.out.println("HelloWorld's constructor...");
} public void setName(String name) {
this.name = name;
} public void hello(){
System.out.println("Hello: " + name);
} }
新建测试方法
public class Main { public static void main(String[] args) { HelloWorld helloWorld = new HelloWorld();
helloWorld.setName("Jackie");
helloWorld.hello();
}
}
最终你会如愿以偿的得到你期望的结果:“Hello:Jackie”
使用Spring后的这一套
使用Spring框架后,我们不能单纯的新建两个类就完事了,怎么说也对不起框架这两个字,于是我们需要:
新建一个Spring的配置文件beans.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:util="http://www.springframework.org/schema/util"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <!-- 配置一个 bean -->
<bean id="helloWorld" class="com.jackie.spring.helloworld.HelloWorld">
<!-- 为属性赋值 -->
<property name="name" value="Jackie"></property>
</bean>
</beans>
测试方法
这里我们大致分为如下几步:
1. 创建 Spring 的 IOC 容器
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
2. 从创建的 IOC 容器中获取 bean 的实例
HelloWorld helloWorld = (HelloWorld) ctx.getBean("helloWorld");
3. 使用 bean实例
helloWorld.hello();
注意:
- ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");HelloWorld helloWorld = (HelloWorld) ctx.getBean("helloWorld");实际上是容器初始化操作,包括本例子中执行helloWorld的构造函数以及执行setName方法
- 这里的ctx.getBean("helloWorld"),是在beans.xml中配置过的,getBean后的名字必须要和beans.xml中定义的id名称一致,否则无法获取该HelloWorld bean的实例
- 同时,我们发现,这里不再需要new了,我们只需要在一个称为IOC的容器中抓我们想要的对象即可,其实本质上来说,这不仅是一个框架的使用,更是一种编程思想的转变。没有使用Spring前,好比买菜要到菜市场,你得提个篮子去菜市场,可是有了Spring,我们轻松多了,把你的篮子甩到门口,自然就有人敲门送菜了。利用佟刚老师的话来说就是“传统的资源查找方式要求组件向容器发起请求查找资源. 作为回应, 容器适时的返回资源. 而应用了 IOC 之后, 则是容器主动地将资源推送给它所管理的组件, 组件所要做的仅是选择一种合适的方式来接受资源. 这种行为也被称为查找的被动形式”
依赖注入
Spring IOC容器之所以能取到HelloWorld类,完全是基于依赖注入机制,骨子里就是反射机制,但是依赖注入的方式有多种,这里做一个简单介绍
属性注入
正如上面beans.xml中声明的那样,定义一个bean,id为helloWorld,class即类的全路径为com.jackie.spring.helloworld.HelloWorld
使用<property>元素为bean注入值,name是bean的属性名称,这里正好也是name,value是bean属性对应的值,其实相当于调用了setName方法,将Jackie传给了HelloWorld的成员变量name。所以如果使用属性注入,需要在bean中定义好相应的set方法。
构造器注入
属性注入是通过set方法注入值,这里的构造器注入,显然是通过构造函数注入值的。举例来说:
新建bean Car类
public class Car { private String company;
private String brand; private int maxSpeed;
private float price; public Car(String company, String brand, float price) {
super();
this.company = company;
this.brand = brand;
this.price = price;
} public Car(String company, String brand, int maxSpeed) {
super();
this.company = company;
this.brand = brand;
this.maxSpeed = maxSpeed;
} public Car(String company, String brand, int maxSpeed, float price) {
super();
this.company = company;
this.brand = brand;
this.maxSpeed = maxSpeed;
this.price = price;
} @Override
public String toString() {
return "Car [company=" + company + ", brand=" + brand + ", maxSpeed="
+ maxSpeed + ", price=" + price + "]";
}
}
相应的,在beans.xml中定义如下
<bean id="car" class="com.jackie.spring.helloworld.Car">
<constructor-arg value="DaZhong" index="1"></constructor-arg>
<constructor-arg value="Shanghai" index="0"></constructor-arg>
<constructor-arg value="250000" type="float"></constructor-arg>
</bean>
这里是根据car类的构造函数来的,value对应构造函数中每个参数的具体值,对应顺序通过index来标示,但是如果car中有多个构造函数像上面的car类,这时候可以通过type参数指定参数的类型是什么,从而决定重载的是那个构造函数。
在测试方法中加入
Car car = (Car) ctx.getBean("car");
System.out.println(car);
得到结果
Car [company=Shanghai, brand=DaZhong, maxSpeed=0, price=250000.0]
同时这里简单介绍下如何在beans.xml中声明一个bean引用其他bean
新建User类
public class User { private String userName;
private List<Car> cars; private String wifeName; public String getWifeName() {
return wifeName;
} public void setWifeName(String wifeName) {
System.out.println("setWifhName: " + wifeName);
this.wifeName = wifeName;
} public String getUserName() {
return userName;
} public void setUserName(String userName) {
this.userName = userName;
} public List<Car> getCars() {
return cars;
} public void setCars(List<Car> cars) {
this.cars = cars;
} public User() {
System.out.println("User's Construtor...");
} @Override
public String toString() {
return "User [userName=" + userName + ", cars=" + cars + "]";
} public void init(){
System.out.println("init method...");
} public void destroy(){
System.out.println("destroy method...");
} }
在beans.xml中声明
<bean id="user" class="com.atguigu.spring.helloworld.User">
<property name="userName" value="Jackie"></property>
<property name="car" ref="car"></property>
</bean>
测试类中加入
User user = (User) ctx.getBean("user");
System.out.println(user);
最终得到结果
User [userName=Jackie, cars=[Car [company=Shanghai, brand=DaZhong, maxSpeed=0, price=250000.0]]
注意:这里也可以使用内部bean的方式,而不需要通过ref属性指定其他bean
<bean id="user" class="com.atguigu.spring.helloworld.User">
<property name="userName" value="Jack"></property>
<property name="car">
<bean class="com.jackie.spring.helloworld.Car">
<constructor-arg value="DaZhong" index="1"></constructor-arg>
<constructor-arg value="Shanghai" index="0"></constructor-arg>
<constructor-arg value="250000" type="float"></constructor-arg>
</bean>
</property>
</bean>
至此,我们了解了
- Spring是什么
- 如何创建一个Spring工程
- 如何写基于Spring框架的HelloWorld
- 两种依赖注入的方式属性注入和构造器注入
- bean与bean之间的相互引用以及内部bean的概念
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!如果您想持续关注我的文章,请扫描二维码,关注JackieZheng的微信公众号,我会将我的文章推送给您,并和您一起分享我日常阅读过的优质文章。
友情赞助
如果你觉得博主的文章对你那么一点小帮助,恰巧你又有想打赏博主的小冲动,那么事不宜迟,赶紧扫一扫,小额地赞助下,攒个奶粉钱,也是让博主有动力继续努力,写出更好的文章^^。
1. 支付宝 2. 微信
学习Spring——依赖注入的更多相关文章
- Spring学习笔记——Spring依赖注入原理分析
我们知道Spring的依赖注入有四种方式,各自是get/set方法注入.构造器注入.静态工厂方法注入.实例工厂方法注入 以下我们先分析下这几种注入方式 1.get/set方法注入 public cla ...
- Spring学习(一)---依赖注入和控制反转
Spring Spring是一个从实际开发中抽出来的框架,因此它完成了大量开发中的通用步骤,留给开发者的仅仅是与特定应用相关的部分,从而大大提高了企业应用的开发效率. Spring为企业应用的开发提供 ...
- Java Web系列:Spring依赖注入基础
一.Spring简介 1.Spring简化Java开发 Spring Framework是一个应用框架,框架一般是半成品,我们在框架的基础上可以不用每个项目自己实现架构.基础设施和常用功能性组件,而是 ...
- 二十7天 春雨滋润着无形 —Spring依赖注入
6月11日,明确."夏条绿已密,朱萼缀明鲜.炎炎日正午,灼灼火俱燃." IT人习惯把详细的事物加工成的形状一致的类.正是这种一致,加上合适的规范.才干彰显对象筋道的牙感和bean清 ...
- Spring依赖注入原理分析
在分析原理之前我们先回顾下依赖注入的概念: 我们常提起的依赖注入(Dependency Injection)和控制反转(Inversion of Control)是同一个概念.具体含义是:当某个角色( ...
- Helloworld之Spring依赖注入/控制反转(DI/IoC)版
Helloworld之Spring依赖注入/控制反转(DI/IoC)版 作者:雨水, 日期:2014-10-29 摘要:本文主要用于培训刚開始学习的人理解Spring中的依赖注入的基本概念. 先介绍依 ...
- Spring依赖注入(IOC)那些事
小菜使用Spring有几个月了,但是对于它的内部原理,却是一头雾水,这次借着工作中遇到的一个小问题,来总结一下Spring. Spring依赖注入的思想,就是把对象交由Spring容器管理,使用者只需 ...
- Spring依赖注入三种方式详解
在讲解Spring依赖注入之前的准备工作: 下载包含Spring的工具jar包的压缩包 解压缩下载下来的Spring压缩包文件 解压缩之后我们会看到libs文件夹下有许多jar包,而我们只需要其中的c ...
- Spring依赖注入:注解注入总结
更多11 spring 依赖注入 注解 java 注解注入顾名思义就是通过注解来实现注入,Spring和注入相关的常见注解有Autowired.Resource.Qualifier.S ...
随机推荐
- 多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)
前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...
- PHP源码分析-变量
1. 变量的三要素变量名称,变量类型,变量值 那么在PHP用户态下变量类型都有哪些,如下: // Zend/zend.h #define IS_NULL 0 #define IS_LONG 1 #de ...
- favicon.ioc使用以及注意事项
1.效果 2.使用引入方法 2.1 注意事项:(把图标命名为favicon.ico,并且放在根目录下,同时使用Link标签,多重保险) 浏览器默认使用根目录下的favicon.ico 图标(如果你并没 ...
- Node.js:dgram模块实现UDP通信
1.什么是UDP? 这里简单介绍下,UDP,即用户数据报协议,一种面向无连接的传输层协议,提供不可靠的消息传送服务.UDP协议使用端口号为不同的应用保留其各自的数据传输通道,这一点非常重要.与TCP相 ...
- angular2系列教程(十一)路由嵌套、路由生命周期、matrix URL notation
今天我们要讲的是ng2的路由的第二部分,包括路由嵌套.路由生命周期等知识点. 例子 例子仍然是上节课的例子:
- 【Machine Learning】机器学习及其基础概念简介
机器学习及其基础概念简介 作者:白宁超 2016年12月23日21:24:51 摘要:随着机器学习和深度学习的热潮,各种图书层出不穷.然而多数是基础理论知识介绍,缺乏实现的深入理解.本系列文章是作者结 ...
- 如何定位Oracle数据库被锁阻塞会话的根源
首先再次明确下,数据库因为要同时保证数据的并发性和一致性,所以操作有锁等待是正常的. 只有那些长时间没有提交或回滚的事物,阻塞了其他业务正常操作,才是需要去定位处理的. 1.单实例环境 2.RAC环境 ...
- 我大中华微软MVP中国区人才库
刘海峰:国内知名微软开源技术网站51Aspx 创始人,十年以上的Asp.net从业经验,微软MSDN特约讲师.Teched讲师.ImagineCup大赛评委.人大出版社研修班特约讲师,曾多次受邀访问美 ...
- css样式之超出隐藏
文本超出部分隐藏,总结两种方法. 1.单行隐藏 html代码 <div class="mi">当文字超过范围的时候,超出部分会隐藏起来.</div> css ...
- Html 制作相册
本文主要讲述采用Html5+jQuery+CSS 制作相册的小小记录. 主要功能点: Html5进行布局 调用jQuery(借用官网的一句话:The Write Less, Do More)极大的简化 ...