spring入门(一)
前面介绍了spring环境的搭建,在搭建spring环境的时候分为java环境和javaWeb环境,在javaWeb环境下通常会结合springMVC使用,在java项目中只需要把spring的包导入工程中,一般初学者会把所有的包全部导入,然后就可以通过获得applicationContext,把类的实例化交给spring管理,然后从spring容器中获得类的实例。
spring中有控制反转(Ioc)和依赖注入(DI)两个概念,Ioc和DI是spring的核心概念,同时也是一种新的编程思想。
控制反转(Ioc)
控制反转,顾名思义就是控制权的改变,在没有接触spring之前,我们要使用一个类的实例,必须使用new的方式生成一个对象,这个过程的主动权掌握在程序员亦自己写的程序中,但是使用了spring之后,实例的创建不再由程序员手动实现,而是由spring容器来完成,实现了控制的反转,即主动权交给了spring的IOC容器。
依赖注入(DI)
一个类包括属性和方法,在创建了实例对象之后,或者在创建实例对象的同时,需要初始化成员变量(属性),在spring之前成员变量的初始化可以通过构造方法或setXXX方法;在spring出现之后,由于实例的创建交给了spring的IOC容器,那么成员变量的初始化也依赖于IOC容器,由容器去注入成员变量的值。
上面介绍了IOC和DI两个概念,可以得出IOC和DI其实是在做一件事,就是spring的IOC容器创建实例对象,一切对象的实例化都交给了spring容器,在程序中不必手动使用new的方式实例化变量。
spring提供两种不同的方式来配置spring,一种是配置文件(XML),另一种是基于注解(Annotation)。下面针对IOC和DI使用两种方式一一做介绍
在介绍之前必须了解如何在java项目中获得spring容器,也即ApplicationContext。
ClassPathXmlApplicationContext cpac=new ClassPathXmlApplicationContext("classpath:applications.xml");
获取ApplicationContext的方式有三种,这里使用的ClassPathXmlApplicationContext,ClassPathApplicationContext是ApplicationContext的子类,这里的cpac就是spring的IOC容器,通过它的getBean()方法可以获得容器中已经初始化的实例。
配置文件(XML)
假如我们有下面的学生类(student)
package com.cn.study.day1; public class Student {
private String id;
private String name;
private String age; public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";
}
//在有了有参的构造函数,必须要提供一个无参构造
public Student(String id, String name) {
this.id = id;
this.name = name;
}
//无参构造
public Student() { } public void init(){
System.out.println("我正在初始化!");
}
public void destroy(){
System.out.println("我将要被销毁了,。再见!");
}
}
此类有三个属性id、name、age,下面通过配置文件的方式,在spring的配置文件中配置,
<bean id="student" class="com.cn.study.day1.Student">
<property name="id" value="1"></property>
<property name="name" value="测试"></property>
<property name="age" value="23"></property>
</bean>
在spring的配置文件中配置<bean>标签,id属性在配置文件中必须唯一,class属性指定类的权限类名,下面有<property>标签,指定Student的三个属性,且指定了属性值,测试结果如下,
Student [id=1, name=测试, age=23]
这里可以看到输出了配置的值,这种方式是使用属性注入的方式,要求必须有setXXX方法,还有另外一种方式,通过构造方法的方式注入,
<!--构造方法注入-->
<bean id="student2" class="com.cn.study.day1.Student" init-method="init" destroy-method="destroy">
<constructor-arg name="id" value="2"></constructor-arg>
<constructor-arg name="name" value="test2"></constructor-arg>
</bean>
既然是通过构造方法的方式注入,那么在Student类中必须要有这个构造方法,在上面的Student类中已经有了有参的构造方法,我们知道在自定义了有参的构造方法之后,系统不会再默认的提供无参构造,我们还必须添加无参构造,下面看测试结果,
Student [id=2, name=test2, age=null]
由于我们只注入了id、name两个属性,这里可以打印出,age由于未赋值且其类型为String,则默认为null。
上面是通过配置文件的方式,配置了根据属性、构造方法注入的方式,这个例子是比较简单的,下面看一个复杂的例子,在程序中经常会采用分层、面向接口编程的思绪,
DAO接口
package com.cn.study.day1.inter; public interface dbDAO { //一个简单的dao层的保存接口
public void save(String str);
}
service接口
package com.cn.study.day1.inter; public interface ServiceInter { /**
* service层的保存方法
*/
public void save(String str);
}
DAO实现类
package com.cn.study.day1.inter.impl; import com.cn.study.day1.inter.dbDAO; public class DbDAOImpl implements dbDAO { @Override
public void save(String str) {
// TODO Auto-generated method stub System.out.println(str+",我会执行数据插入操作!你会吗?");
} }
service实现类
package com.cn.study.day1.inter.impl; import com.cn.study.day1.inter.ServiceInter;
import com.cn.study.day1.inter.dbDAO; public class ServiceImpl implements ServiceInter {
//DAO接口对象
private dbDAO dbDAO;
//setXXX方法
public void setDbDAO(dbDAO dbDAO) {
this.dbDAO = dbDAO;
}
@Override
public void save(String str) {
// TODO Auto-generated method stub
if(str!=null&&!"".equals(str)){
dbDAO.save(str);
System.out.println("执行完了DAO层的方法,我是service层的方法!");
}
}
}
在service的实现类中有一个DAO层的接口对象,我们下面看这种是如何根据属性注入的,
<!--下面是一个复杂的属性注入的例子-->
<bean id="dbDao" class="com.cn.study.day1.inter.impl.DbDAOImpl"></bean>
<!--下面的这个类,有一个dbDAO的属性,需要进行属性注入,必须提供一个set方法-->
<bean id="service" class="com.cn.study.day1.inter.impl.ServiceImpl">
<property name="dbDAO" ref="dbDao"></property>
</bean>
首先,配置DAO层的bean,这里的class属性必须配置其实现类,然后配置service的实现类,在ServiceImpl中有一个dbDAO类型的属性,使用ref属性引用上面的bean。测试结果如下,
我是测试方法,我会执行数据插入操作!你会吗?
执行完了DAO层的方法,我是service层的方法!
ref属性可以引用spring配置文件中的bean,使用id的值。
通过上面的介绍,可以知道使用配置文件这种方式可以很方便的配置,但是当需要配置的类很多,且依赖很多的情况下,这种方式会很繁琐,那么另外一种方式便派上了用场。
注解(Annotation)
spring提供@Component、@Repository、@Controller、@Service四种注解,其实,只使用@Component一个便可以做到,@Repository、@Controller、@Service只是针对不同的层设置的,可以更加明显,@Repository对应DAO层,@Controller对应控制层,@Service对应服务层,使用这三个注解可以明显的分层,使系统容易理解,也可以只使用@Component。
使用了注解需要开启组件自动扫描机制,在spring的配置文件中开启组件自动扫描机制,需要context命名空间的支持,下面是一个配置文件的例子,
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd" >
<!--spring 自动检测-->
<context:component-scan base-package="com.cn.study.day1" />
</beans>
在spring配置文件的头部添加context命名空间的支持,然后使用<context:component-scan base-package="">标签开启组件扫描,base-package属性指定扫描的基包,此包及此包下的子包都会进行扫描。开启了组件扫描之后,还需要自动注入,网上有说需要:<context:annotation-config/>,其实前面的组件扫描已经包含了此标签的作用,为此不需要配置此标签了,自动注入默认根据类型(byType)进行注入,还有根据名字注入(byName)即bean中id的值,还有根据构造方法注入(constructor)。自动注入需要@Aotuwired注解,此注解可以放在属性上,也可以放在setXXX方法上,放在属性上则可以省略setXXX方法,下面是具体的例子
package com.cn.study.day1; import org.springframework.stereotype.Component; @Component("su")
public class StudentAnnotation { public void print(){
System.out.println("我是使用注解生成的类!");
}
}
在类上使用@Component注解,且指定了实例的名为su,如果不指定则默认为类名称首字母小写,即studentAnnotation。
下面是一个自动扫描和自动注入的例子,
package com.cn.study.day1.inter.impl; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import com.cn.study.day1.inter.ServiceInter;
import com.cn.study.day1.inter.dbDAO;
@Service
public class ServiceImpl implements ServiceInter {
//DAO接口对象
@Autowired
private dbDAO dbDAO;
//setXXX方法
public void setDbDAO(dbDAO dbDAO) {
this.dbDAO = dbDAO;
}
@Override
public void save(String str) {
// TODO Auto-generated method stub
if(str!=null&&!"".equals(str)){
dbDAO.save(str);
System.out.println("执行完了DAO层的方法,我是service层的方法!");
}
}
}
类上使用了@Service注解,属性上使用了@Autowired注解,这时setDbDAO()方法可以不要。@Autowired注解就是为了省略setXXX方法的,@Autowired注解默认使用的按照类型注入,如果存在多个相同类型的实例,这里自动注入会失败,为了可以正确注入,引入另外一个注解@Qualifier(value=""),此注解的value属性可以指定一个bean的id值,做到自动注入。
@Qualifier可以用在属性或者setXXX方法上。
综上,通过配置文件和注解两种方式介绍了依赖注入。
有不正之处欢迎指出,谢谢。
spring入门(一)的更多相关文章
- Spring入门学习(一)
SpringMVC基础平台补充(2016.03.03) 如果想要开发SpringMVC,那么前期依次安装好:JDK(jdk-8u74-windows-x64,安装后配置环境变量JAVA_HOME和CL ...
- Spring入门(10)-Spring JDBC
Spring入门(10)-Spring JDBC 0. 目录 JdbcTemplate介绍 JdbcTemplate常见方法 代码示例 参考资料 1. JdbcTemplate介绍 JdbcTempl ...
- Spring入门(9)-AOP初探
Spring入门(9)-AOP初探 0. 目录 什么是面向切面编程 AOP常见术语 AOP实例 参考资料 1. 什么是面向切面编程 Aspect Oriented Programming(AOP),即 ...
- Spring入门(8)-基于Java配置而不是XML
Spring入门(8)-基于Java配置而不是XML 本文介绍如何应用Java配置而不是通过XML配置Spring. 0. 目录 声明一个简单Bean 声明一个复杂Bean 1. 声明一个简单Bean ...
- Spring入门(7)-自动检测Bean
Spring入门(7)-自动检测Bean 本文介绍如何自动检测Bean. 0. 目录 使用component-scan自动扫描 为自动检测标注Bean 1. 使用component-scan自动扫描 ...
- Spring入门(6)-使用注解装配
Spring入门(6)-使用注解装配 本文介绍如何使用注解装配. 0. 目录 使用Autowired 可选的自动装配 使用Qualifier选择 1. 使用Autowired package com. ...
- Spring入门(5)-自动装配Bean属性
Spring入门(5)-自动装配Bean属性 本文介绍如何装配Bean属性. 0. 目录 ByName ByType constructor 默认自动装配 混合使用自动装配和显示装配 1. ByNam ...
- Spring入门(4)-注入Bean属性
Spring入门(4)-注入Bean属性 本文介绍如何注入Bean属性,包括简单属性.引用.内部Bean.注入集合等. 0. 目录 注入简单值 注入引用 注入内部Bean 装配集合 装配空值 使用命名 ...
- Spring入门(3)-Spring命名空间与Bean作用域
Spring入门(3)-Spring命名空间与Bean作用域 这篇文章主要介绍Spring的命名空间和Bean作用域 0. 目录 Spring命名空间 Bean作用域 1. Spring命名空间 在前 ...
- Spring入门(2)-通过构造器注入Bean
Spring入门(2)-通过构造器注入Bean 前一篇文章将了最基本的spring例子,这篇文章中,介绍一下带有参数的构造函数和通过构造器注入对象引用. 0. 目录 带有参数的构造函数 通过构造器注入 ...
随机推荐
- 学习ASP.NET MVC(四)——我的第一个ASP.NET MVC 实体对象
今天我将根据数据库中的表结构添加一些类.这些类将成为这个ASP.NET MVC应用程序中“模型”的一部分. 我们使用Entity Framework(实体框架)来定义和使用这些模型类,并且 ...
- java基础,继承类题目:编写一个Java应用程序,该程序包括3个类:Monkey类、People类和主类 E
21.编写一个Java应用程序,该程序包括3个类:Monkey类.People类和主类 E.要求: (1) Monkey类中有个构造方法:Monkey (String s),并且有个public vo ...
- Winform实现Shp-栅格图形文件的读取与显示(外加shp转WKB格式存入oracle)附源码
前言:上学期GIS空间数据库课程设计时,老师让实现Shp-栅格图形文件的读取与显示,外加shp转WKB格式存入oracle,不使用第三方类库,花了一天时间在网上找了一些资料,实现了一个简单的栅格图形文 ...
- 【转】中间代码opcode的执行
原文链接:http://www.orlion.ga/941/ 原文:http://www.nowamagic.net/librarys/veda/detail/1543 假如我们现在使用的是CLI模式 ...
- 【.Net底层剖析】3.用IL来理解属性
.Net底层剖析目录章节 1.[深入浅出.Net IL]1.一个For循环引发的IL 2.[.Net底层剖析]2.stfld指令-给对象的字段赋值 3.[.Net底层剖析]3.用IL来理解属性 未完待 ...
- 开发笔记:基于EntityFramework.Extended用EF实现指定字段的更新
今天在将一个项目中使用存储过程的遗留代码迁移至新的架构时,遇到了一个问题——如何用EF实现数据库中指定字段的更新(根据UserId更新Users表中的FaceUrl与AvatarUrl字段)? 原先调 ...
- Apache+MySQL+PHP开发环境的搭建(二)
通过自主选择相应的apache,mysql,php等软件,根据自己的应用开发需求进行安装.此方法搭建的环境自主性较强,搭建过程较为复杂,繁琐. 1.所需软件: Apache: http-2.2.22- ...
- 2015年,从毕业到工作的几点感悟(Android开发新人)
锄禾日当午,汗滴禾下土. 2015年,从毕业到工作的几点感悟(Android开发): 多用三方类库:(成长经验:尽量不要自己手动实现网络上已经有的优秀开源类库的功能,例如: 网络请求:常见 ...
- Java中不同的并发实现的性能比较
Fork/Join框架在不同配置下的表现如何? 正如即将上映的星球大战那样,Java 8的并行流也是毁誉参半.并行流(Parallel Stream)的语法糖就像预告片里的新型光剑一样令人兴奋不已.现 ...
- 谷歌插件Image downloader开发之popup
Image downloader的交互逻辑是这样的:用户点击Image downloader的图标,会向页面(content script,见上一篇文章:谷歌插件Image downloader开发之 ...