Spring依赖注入

原创 2018年04月15日 16:37:31

1:为了降低Java开发的复杂性,Spring采取了4种关键策略
    通过POJO的轻量级和最小侵入性编程;
    通过依赖注入和面向接口实现松耦合;
    基于切面和惯例进行声明式编程;
    通过切面和模板减少样板式代码;
Spring竭力避免因自身的API而弄乱应用代码,不会强迫你实现Spring规范的接口或者继承Spring规范的类。相反,在基于Spring构建的应用中,他的类通常没有任何痕迹表明你使用了Spring。最坏的场景,一个类或许会使用Spring注解,但它依旧是POJO.
从这点看,配置还是注解都是各有利弊,配置虽然略显繁琐,但与代码独立。注解虽然便于快速开发,但还是具有一定耦合性。
例1:
public class Student1 implements Person{
	private Teacher teacher;

	public Student1() {
		this.teacher = new Teacher();//与Teacher紧耦合
	}
	
	public void study() {
		teacher.teach();
	}
}

例2:

public class Student implements Person{
	private Teacher teacher;

	public Student(Teacher teacher) {
		this.teacher = teacher;
	}
	
	public void study() {
		teacher.teach();
	}
}

这两个例子简略的展示了紧耦合所带来的限制,例2并没有自行的传递一个对象,而是在构造的时候将任务作为构造器参数传入,这是依赖注入的方式之一,既构造器注入
再扩展一下,假如例1中的teacher是体育老师,或者美术老师,而例2中的teacher是所有的老师,那么例1的劣势更将凸显出来,而例2却能够相应不同的teacher的操作,实现了没有与任何特定的teacher发生耦合,他并不关心是哪个具体的teacher,这就是DI【依赖注入】所带来的最大收益——松耦合。如果一个对象只通过接口【而不是具体实现或初始化过程】来表明依赖关系,那么这种依赖就能够在对象本身毫不知情的情况下,用不同的具体实现进行代替。
  但是,耦合具体两面性。一方面,紧密耦合的代码难以测试,难以复用,难以理解,并且典型的表现出“打地鼠”的bug特征,修复完一个bug,将会出现其他bug。另一方面,一定程度的耦合又是必须的,完全没有耦合的代码什么也做不了。为了完成有实际意义的功能,不同的类必须以适当的方式进行交互,总而言之,耦合是必须的,但应当被小心谨慎的使用。
         那么,怎样将特定的teacher传递给student呢,创建应用组件之间协作的行为通常称为装配。
Spring有多种装配bean的方式,采用XML是很常见的。以下为例展示:
package com.spring.dao;

public interface TeacherDao {
	
	public void teach();
}

Teacher实现类:
import com.spring.dao.TeacherDao;

public class TeacherDaoImple implements TeacherDao{

	public void teach() {
		System.out.println("老师在讲课");
	}
}

Student类:
import com.spring.dao.TeacherDao;

public class StudentService{

	private TeacherDao teacherDao;
	
	public void setTeacherDao(TeacherDao teacherDao) {
		this.teacherDao = teacherDao;
	}
	
	public void lean() {
		teacherDao.teach();
	}

}

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"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="studentService"  class="com.spring.service.StudentService">
		<property name="teacherDao"  ref="teacher"></property>
	</bean>
	<bean id="teacher" class="com.spring.dao.imple.TeacherDaoImple"></bean>
	
</beans>

测试类:
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.spring.service.StudentService;

public class StudentTest {
	private ApplicationContext atc =  new ClassPathXmlApplicationContext("Student.xml");

	@Test
	public void test1(){
		StudentService stu = atc.getBean(StudentService.class);
		stu.lean();	
	}
}
测试结果:
信息: Loading XML bean definitions from class path resource [Student.xml]
老师在讲课

Spring还支持使用JAVA来描述配置。其作用与XML是相同的。
import javax.annotation.Resource;
import org.springframework.stereotype.Component;

@Component(value="student")
public class Student implements Person{
	@Resource
	private Teacher teacher;

	public Student(Teacher teacher) {
		this.teacher = teacher;
	}
	
	public void study() {
		teacher.teach();
	}
}

尽管Student依赖与Teacher,但是他并不知道传递给他的是什么具体类型的teacher,也不知道它来自何方,只有Spring通过他的配置,能够了解这些组成部分是如何装配起来的,这样的话,就可以在不改变所依赖的类的情况下,修改依赖关系。
这里即通过Student.xml文件创建了Spring应用上下文。
    这里需要注意的是,Student类中需要有一个实际可使用的默认构造方法,如果声明了一个有参的构造方法,那么还需要声明一个无参的构造方法,否则无法自动创建bean。
    有参的构造方法时,没有声明无参构造:
public class StudentService{

	private TeacherDao teacherDao;
	
	public StudentService(TeacherDao teacherDao) {
		super();
		this.teacherDao = teacherDao;
	}

	public void setTeacherDao(TeacherDao teacherDao) {
		this.teacherDao = teacherDao;
	}
	
	public void lean() {
		teacherDao.teach();
	}

}

测试类执行结果:
警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'studentService' defined in class path resource [Student.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.spring.service.StudentService]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.spring.service.StudentService.<init>()

所以建议保持始终显式的声明一个无参构造:
public class StudentService{

	private TeacherDao teacherDao;
	
	public StudentService() {
		super();
	}

	public StudentService(TeacherDao teacherDao) {
		super();
		this.teacherDao = teacherDao;
	}

	public void setTeacherDao(TeacherDao teacherDao) {
		this.teacherDao = teacherDao;
	}
	
	public void lean() {
		teacherDao.teach();
	}

}

测试类执行结果:
信息: Loading XML bean definitions from class path resource [Student.xml]
老师在讲课

版权声明:转载请注明出处 https://blog.csdn.net/tangmingxin0529/article/details/79950391

Could not instantiate bean class [com.bjsxt.service.UserService]: No default constructor found;

Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory...
  • randomnet
  • randomnet
  • 2013-04-28 21:44:32
  • 11002

Spring入门--控制反转(IOC)与依赖注入(DI)

1.控制反转(Inversion of Control)与依赖注入(Dependency Injection) 控制反转即IoC (Inversion of Control),它把传统上由程序代码直接...
  • hy6688_
  • hy6688_
  • 2014-10-31 18:46:16
  • 9451

Spring 依赖注入四种方式

纸上得来终觉浅 1.构造器注入 AnimalDao: package com.roadArchitectWeb.dao; public interface AnimalDao { /*所有动物有一个...
  • Jintao_Ma
  • Jintao_Ma
  • 2016-04-05 19:35:29
  • 946

关于spring 依赖注入有什么好处

最近在网上看到很多人提问,关于spring 依赖注入有什么好处 ?以下是某人说的一句话:"我看了,好处就是说,如果某一天实现类变了,在xml里改一下就行了,可是用原始的java new关键字,我也可以...
  • hanxiaoshuang321123
  • hanxiaoshuang321123
  • 2012-04-17 21:33:52
  • 3331

spring框架学习(二)依赖注入

spring框架为我们提供了三种注入方式,分别是set注入,构造方法注入,接口注入。接口注入不作要求,下面介绍前两种方式。 1,set注入   采用属性的set方法进行初始化,就成为set...
  • lishuangzhe7047
  • lishuangzhe7047
  • 2014-03-07 23:04:54
  • 127932

spring依赖注入失败原因

今天碰到一个奇葩项目,一朋友叫我帮忙解决一下错误,我看了一下代码,内容很简单,基本上也都是些小错误,改完后运行,结果就报了个依赖注入失败失败,先贴上错误信息:严重: Context initializ...
  • xiaojie119120
  • xiaojie119120
  • 2017-07-12 18:58:48
  • 894

Spring进阶之路(1)-Spring核心机制:依赖注入/控制反转

我们经常会遇到这样一种情景,就是在我们开发项目的时候经常会在一个类中调用其他的类中的方法,来完成我们期望的任务,大部分的情况下往往会采用在当前需要的这个类里面new一个实例出来,然后调用他的方法,那么...
  • wangyang1354
  • wangyang1354
  • 2016-02-28 16:41:50
  • 3313

spring的依赖注入怎么理解

http://zhidao.baidu.com/question/399874366.html?fr=qrl&index=4&qbl=topic_question_4&word=%D2%C0%C0%B...
  • a1049107922
  • a1049107922
  • 2016-09-03 11:38:13
  • 1289

spring的依赖注入和工作原理

1、设置注入 IoC容器使用setter方法来注入被依赖的实例 2、构造注入 构造实例,完成依赖实例的初始化。 --> 创建实例时机不同 设置注入,先通过无参构造器创建一个调用者实例,在调...
  • u011513323
  • u011513323
  • 2014-07-29 15:58:35
  • 7367
收藏助手
不良信息举报
您举报文章:Spring依赖注入
举报原因:
原因补充:

(最多只允许输入30个字)