您的位置:首页 > 编程语言 > Java开发

spring系列(二):依赖注入

2017-12-20 16:54 232 查看
一   初识Spring

1.1   企业级应用开发

       在学习Spring前,首先让我们了解一下企业级应用。企业级应用是指那些为商业组织、大型企业而创建并部署的解决方案及应用。这些大型企业级应用的结构复杂,涉及的外部资源众多,事务密集,数据规模大,用户数量多,有较强的安全性考虑和较高的性能要求。

     当代的企业级应用绝不可能是一个个的独立系统。在企业中,一般都会部署多个进行交互的应用,同时这些应用又都有可能与其他企业的相关应用连接,从而构成一个结构复杂的、跨越Internet的分布式企业应用集群。此外,作为企业级应用,不但要有强大的功能,还要能够满足未来业务需求的变化,易于扩展和维护。

     传统JavaEE解决企业级应用问题时的“重量级”架构体系,使它的开发效率、开发难度和实际的性能都令人失望。正在人们苦苦寻找解决办法的时候,Spring以一个“救世主”的形象出现在广大的Java程序员面前。

     说到Spring就得提到它的作者Rod Johnson,2002年他编写了《Expert One-on-One Java EE设计与开发》一书。在书中,他对传统的Java EE技术日益臃肿和低效提出了质疑,他觉得应该有更便捷的做法,于是提出了Interface 2.1,也就是Spring框架的雏形。他提出了技术以实用为准的主张,引发了人们对“正统”Java E.E的反思。2003年2月Spring框架正式成为一个开源项目,并发布于SourceForge中。

     Spring致力于JavaEE应用的各种解决方案,而不是仅仅专注于某一层的方案。可以说,Spring是企业应用开发的“一站式”选择,Spring贯穿表现层、业务层、持久层。然而,Spring并不想取代那些已有的框架,而是以高度的开放性与它们无缝整合。

1.2 Spring的“绿草丛”

        Spring确实给人一种格外清新、爽朗的感觉,仿佛微雨后的绿草丛,讨人喜欢,又蕴藏着勃勃生机。Spring是一个轻量级框架,它大大简化了Java企业级开发,提供了强大、稳定的功能,又没有带来额外的负担,让人们在使用它做每一件事情的时候都有得体和优雅的感觉。Spring有两个主要目标:一是让现有技术更易于使用,二是促进良好的编程习惯(或者称为最佳实践)。

        Spring是一个全面的解决方案,但它坚持一个原则:不重新发明轮子。已经有较好解决方案的领域,Spring绝不做重复性的实现。例如,对象持久化和ORM,Spring只是对现有的JDBC、Hibernate等技术提供支持,使之更易用,而不是重新做一个实现。

       Spring框架由大约20个功能模块组成。这些模块被分组成6个部分,分别是Core Container、 Data Access/lntegration、Web、AOP(Aspect Oriented Programming)、Instrumentation及Test,如下图所示。



        Spring Core是框架的最基础部分,提供了IoC特性。Spring Context为企业级开发提供了便利和集成的工具。Spring AOP是基于Spring Core的符合规范的面向切面编程的实现。Spring JDBC提供了JDBC的抽象层,简化了JDBC编码,同时使代码更健壮。Spring ORM部分对Hibernate等ORM框架提供了支持。Spring Web为Spring在Web应用程序中的使用提供了支持。关于Spring的其他功能模块在开发中的作用,可以查阅Spnng的文档进行了解,这里不再赘述。

二   spring IOC   

2.1  IOC简介   

      控制反转(Inversionof Control,IoC),也被称为依赖注入(Dependency Injection,DI),是面向对象编程中的一种设计理念,用来减低程序代码之间的耦合度。

首先考虑什么是依赖。依赖,在代码中一般指通过局部变量、方法参数、返回值等建立的对于其他对象的调用关系。例如,在A类的方法中,实例化了B类的对象并调用其方法以完成特定的功能,我们就说A类依赖于B类。

        几乎所有的应用都是由两个或更多的类通过彼此合作来实现完整的功能。类与类之间的依赖关系增加了程序开发的复杂程度,我们在开发一个类的时候,还要考虑对正在使用该类的其他类的影响。

2.2  IOC入门案例

环境: jdk1.7   spring3.2.2

1.      建立工程,导入包



2.   建立核心配置文件ApplicationContext.xml



命名空间的编写

<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-3.0.xsd">
可以参考web.xml  和下图



3.   入门程序

=================HelloSpring.java======================

package com.obtk.spring;

public class HelloSpring {
private String who;

private String greet;

public HelloSpring() {
System.out.println("默认构造方法执行了");
}
public void setGreet(String greet) {
this.greet = greet;
}

public void setWho(String who) {
this.who = who;
}

public void print(){
System.out.println("hello:"+who+","+greet);
}
}
4.  配置
<?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-3.0.xsd"> <bean id="hello" class="com.obtk.spring.HelloSpring">
<property name="who" value="麻子"></property>
<property name="greet" value="欢迎来到spring的世界"></property>
</bean>

</beans>5.  测试代码
package com.obtk.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.obtk.spring.HelloSpring;

public class TestSpring2 {
public static void main(String[] args) {
ApplicationContext context=
new ClassPathXmlApplicationContext("ApplicationContext.xml");
HelloSpring hello=(HelloSpring)context.getBean("hello");
hello.print();
}
}


2.3  P标签注入

        Spring配置文件从2.0版本开始采用schema形式,使用不同的命名空间管理不同类型的配置,使得配置文件更具扩展性。例如我们可以使用p命名空间简化属性的注入。p命名空间的特点是使用属性而不是子元素的形式配置Bean的属性,从而简化了Bean的配置。



如上图所示,p标签注入需要导入p命名空间。p标签注入是set注入的另一种形式,具体代码省略。

2.4 构造注入 

       在前面的案例中,我们使用Spring通过setter访问器实现了对属性的赋值,这种做法被称为设值注入。除此之外,Spring还提供了通过构造方法赋值的能力,称为构造注入。

构造注入案例1
package com.obtk.spring;

public class HelloSpring {
private String who;

private String greet;

public HelloSpring() {
System.out.println("默认构造方法执行了");
}
//用于构造注入
public HelloSpring(String who,String greet){
this.who=who;
this.greet=greet;
}

public void setGreet(String greet) {
this.greet = greet;
}

public void setWho(String who) {
this.who = who;
}

public void print(){
System.out.println("hello:"+who+","+greet);
}
}


配置
<!-- 构造注入 -->
<bean id="hello" class="com.obtk.spring.HelloSpring">
<constructor-arg value="欢迎来到spring的世界" index="1"></constructor-arg>
<constructor-arg value="麻子" index="0"></constructor-arg>
</bean>

构造注入案例2

package com.obtk.biz;

import com.obtk.dao.IUserDao;
import com.obtk.entitys.UserEntity;

public class UserBiz {
private IUserDao userDao;

public UserBiz() {
}

//用于构造注入
public UserBiz(IUserDao userDao){
this.userDao=userDao;
}

public void setUserDao(IUserDao userDao) {
this.userDao = userDao;
}

public int saveUser(UserEntity theUser) {
return userDao.saveUser(theUser);
}

}
配置
<bean id="userDao" class="com.obtk.dao.UserDaoImpl"></bean>
<bean id="userBiz" class="com.obtk.biz.UserBiz">
<constructor-arg ref="userDao"></constructor-arg>
</bean>

构造注入注意事项

(1) 一个<constructor-arg>元素表示构造方法的一个参数,且使用时不区分顺序。当构造方法的参数出现混淆,无法区分时,可以通过<constructor-arg>元素的index属性指

定该参数的位置索引,位置从0开始。<construc tor-arg>元素还提供了type属性用来指定参数的类型,避免字符串和基本数据类型的混淆。

    (2)构造注入的时效性好,在对象实例化时就得到所依赖的对象,便于在对象的初始化方法中使用依赖对象;但受限于方法重载的形式,使用灵活性不足。设值注入使用灵活,但时效性不足,并且大量的setter访问器增加了类的复杂性。Spring并不倾向于某种注入方式,学生应该根据实际情况进行合理的选择。

    当然Spring提供的注入方式不只这两种,只是这两种方式用得最普遍,感兴趣的话可以通过Spring的相关资料了解其他注入方式。

2.5   注入其它类型数据

<!-- local在当前配置文件里面搜索,bean是在整个项目的配置文件里面搜索-->
<bean id="userBiz3" class="com.obtk.biz.UserBiz">
<property name="userDao">
<ref bean="userDao"/>
</property>
</bean>

<!-- 其它数据类型注入 -->
<bean id="stu1" class="com.obtk.entitys.StudentEntity">
<property name="sno" value="1101"></property>
<property name="sname" value="周星<>星"></property>
<property name="age" value="12"></property>
<property name="gender" value="男"></property>
<property name="score" value="93.3"></property>
<property name="hobbyList">
<list>
<value>爬山</value>
<value>游泳</value>
<value>打球</value>
</list>
</property>
<property name="contryMap">
<map>
<entry> <key><value>cn</value> </key>
<value>中华人民共和国</value>
</entry>
<entry> <key><value>us</value> </key>
<value>美利坚合众国</value>
</entry>
<entry> <key><value>en</value> </key>
<value>英格兰</value>
</entry>
</map>
</property>
<property name="props">
<props>
<prop key="cn">中华人民共和国</prop>
<prop key="us">美利坚合众国</prop>
</props>
</property>
</bean>
在XML中有5个预定义的实体引用,如表所示。

符  号

实体引用

符  号

实体引用



<

 

'



>

 

"

&

&

 

 

             严格地讲,在XML中仅有字符“<”和“&”是非法的,其他3个符号是合法的,但是把它们替换为实体引用是个好习惯。

如果一个Bean组件仅在一处需要使用,可以把它定义为内部Bean。关键代码如下示例所示。
<!-- 定义StudentBiz对象,并指定id为studentBiz -->
<bean id="studentBiz" class="biz.impl.StudentBiz">
<!-- 为studentBiz的dao属性赋值,需要注意的是,这里要调用setDao()方法 -->
<property name="studentDao">
<!-- 定义StudentDao -->
<bean class="dao.impl.StudentDao" />
</property>
</bean>

这样,这个UserDao类型的Bean就只能被studentBiz使用,无法被其他的Bean引用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: