spring in action学习笔记一:DI(Dependency Injection)依赖注入之CI(Constructor Injection)构造器注入

一:这里先说一下DI(Dependency Injection)依赖注入有种表现形式:一种是CI(Constructor Injection)构造方法注入,另一种是SI(Set Injection) set 注入。这篇随笔讲的是第一种构造方法注入(Constructor Injection).

其实DI(Dependency Injection)依赖注入你不妨反过来读:注入依赖也就是把"依赖"注入到一个对象中去。那么何为"依赖"呢?依赖就是讲一个对象初始化或者将实例化的时候需要另一个对象,我们把另一个对象成为"依赖"。如构造方法注入(Constructor Injection)就是把依赖当做构造方法的参数注入进去的。如:

//Injection B to A. 我们把B称为依赖。一般情况下B是一个接口,这符合面向接口编程的规范。

public A (B b){

}

二:使用依赖注入的好处是什么?

  1.DI(Dependency Injection)最大的好处是decoupling(解耦)。如上面的代码把B注入给A如果B是一个接口或者抽象类。只要任何一个类实现或者继承B都可以注入给A.因此可以达到解耦的目的。

  2. 依赖注入给谁?        

dependencies injected into the objects that need them.(依赖注入给那些需要他们的对象。)

3.在spring中怎么让依赖传入到被依赖的对象(看上面的代码:怎么把B传入到A中)?

 在这里我引用一下spring in action中的一段文字:(注:我下面的示例代码基本跟spring in action 的一样)

The big question here is,how can you give SlayDragonQuest to BraveKnight ? And how can you give a PrintStream to SlayDragonQuest?

The act of creating associations between application components is commonly referred to as wiring.

spring通过配置配置文件,配置bean的形式,完成装配,又装配实现把依赖注入给需要他们的对象中的。

【我这里还想说明一下配置文件中的一个bean其实就对应一个javabean,也就是一个pojo对象,bean就是javabean的缩写形式而已】

示例代码的目录结构如下图所示:

  上面中的带两个圈的配置文件想说明两个问题:

一个是:new ClassPathXmlApplicationContext("spring-julysecond.xml");//注意这个.xml文件是在src目录下。

    new ClassPathXmlApplicationContext("com/config/spring-julythird.xml")//注意这个.xml文件在com.cofig这个文件下。

另一个问题是DI的解耦问题:spring-julysecond.xml文件中注入的是SlayDragonQuest,spring-julythird.xml注入的是SearchHillQuest.在不改变代码的情况下看传入的Quest的实现类不同,从而打出的结果不同。

spring-julysecond.xml的代码如下:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4        xsi:schemaLocation="http://www.springframework.org/schema/beans
 5 http://www.springframework.org/schema/beans/spring-beans.xsd">
 6     <!--this is constructor injection-->
 7     <!--the act of creating associations between application components is commonly referred to
 8     as wiring-->
 9     <bean id="knight" class="com.qls.impl.BraveKnight">
10         <!-- collaborators and configuration for this bean go here -->
11         <constructor-arg ref="query"></constructor-arg>
12     </bean>
13     <bean id="query" class="com.qls.impl.SlayDragonQuest">
14         <!-- collaborators and configuration for this bean go here -->
15         <constructor-arg value="#{T(System).out}"/>
16     </bean>
17     <!-- more bean definitions go here -->
18 </beans>

//spring-julythird.xml的代码如下:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4        xsi:schemaLocation="http://www.springframework.org/schema/beans
 5 http://www.springframework.org/schema/beans/spring-beans.xsd">
 6     <!--this is constructor injection-->
 7     <!--the act of creating associations between application components is commonly referred to
 8     as wiring-->
 9     <bean id="knight" class="com.qls.impl.BraveKnight">
10         <!-- collaborators and configuration for this bean go here -->
11         <constructor-arg ref="query"></constructor-arg>
12     </bean>
13     <bean id="query" class="com.qls.impl.SearchHillQuest">
14         <constructor-arg value="#{T(System).out}"/>
15     </bean>
16     <!-- more bean definitions go here -->
17 </beans>

//Query接口的代码如下:

 1 package com.qls.inter;
 2
 3 /**
 4  * Created by ${秦林森} on 2017/6/2.
 5  */
 6 public interface Query {
 7     void query();
 8     void embark();
 9 }
10
11     

//Knight的代码如下:

1 package com.qls.inter;
2
3 /**
4  * Created by ${秦林森} on 2017/6/2.
5  */
6 public interface Knight {
7     void embarkOnQuest();
8 }

//Query接口的实现类的代码如下:

//首先是:SlayDragonQuest的代码如下:

 1 package com.qls.impl;
 2
 3 import com.qls.inter.Query;
 4
 5 import java.io.PrintStream;
 6
 7 /**
 8  * Created by ${秦林森} on 2017/6/2.
 9  */
10 public class SlayDragonQuest implements  Query{
11     private PrintStream stream;
12
13     public SlayDragonQuest(PrintStream stream) {
14         this.stream = stream;
15     }
16     @Override
17     public void embark(){
18         stream.println("Embarking on quest to slay the dragon");
19         stream.println("ouyangfeng is the most beautiful woman in the world.");
20     }
21     @Override
22     public void query(){
23         System.out.println("slay dragon quest");
24     }
25 }

//其次是SearchHillQuest的代码如下:

 1 package com.qls.impl;
 2
 3 import com.qls.inter.Query;
 4
 5 import java.io.PrintStream;
 6
 7 /**
 8  * Created by ${秦林森} on 2017/6/3.
 9  */
10 public class SearchHillQuest implements Query{
11     private PrintStream stream;
12
13     public SearchHillQuest(PrintStream stream) {
14         this.stream = stream;
15     }
16
17     @Override
18     public void query() {
19
20     }
21
22     @Override
23     public void embark() {
24        stream.println("the hero search the hill where the damsel was missing");
25     }
26 }

//BraveKnight的代码如下:

 1 package com.qls.impl;
 2
 3 import com.qls.inter.Knight;
 4 import com.qls.inter.Query;
 5 import org.springframework.context.annotation.Configuration;
 6
 7 /**
 8  * Created by ${秦林森} on 2017/6/2.
 9  */
10
11 public class BraveKnight implements Knight{
12     private Query query;
13
14     public BraveKnight(Query query) {
15         this.query = query;
16     }
17
18     @Override
19     public void embarkOnQuest() {
20         query.embark();
21     }
22 }

//测试类的代码如下:

 1 package com.qls.test;
 2
 3 import com.qls.inter.Knight;
 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
 5
 6 /**
 7  * Created by ${秦林森} on 2017/6/2.
 8  */
 9 public class Test {
10     public static void main(String[] args) {
11         /**
12          * 加载配置文件的方式:在src下直接写配置文件的名即可,
13          * 不直接在src下要把前面的包名加上。包名的前面可加也可以不加斜杠/
14          */
15 //        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/com/config/spring-julythird.xml");
16 //        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("com/config/spring-julythird.xml");
17         ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-julysecond.xml");
18         Knight knight = context.getBean(Knight.class);
19         knight.embarkOnQuest();
20         context.close();
21
22     }
23 }
时间: 2024-10-14 05:15:45

spring in action学习笔记一:DI(Dependency Injection)依赖注入之CI(Constructor Injection)构造器注入的相关文章

Spring in Action 学习笔记二-DI

装配bean 2015年10月9日 9:49 ? ? ? ? ? ? Sprng中,对象无需自己负责查找或创建其关联的其他对象.相关,容器负责吧需要相互协作的对象引用赋予各个对象. 创建应用对象之间协作关系的行为通常被称为装配(wiring).这是依赖注入的本质. ? ? ? ? ? ? 声明bean ? ? ? 典型的xml配置文件 ? ? ? ? ? ? 屏幕剪辑的捕获时间: 2015-10-9 10:17 ? ? ? spring核心自带了10个命令空间 ? ? ? ? ? ? 屏幕剪辑的

Spring in Action 学习笔记一

Spring 核心 ? ? ? Spring的主要特性仅仅是 依赖注入DI和面向切面编程AOP ? ? ? JavaBean 1996.12 Javav 规范针对Java定义了软件组件模型,是简单的Java对象不仅可以重用,而且可以轻松的构建更复杂的应用.没有提供诸如事务支持.安全.分布式计算等服务. ? ? ? BJB 1998.3 提供了必须的企业级服务,但是不再简单, 声明式编程简化开发 部署描述符和配套代码实现异常复杂. Java 组件开发, AOP 和DI 为POJO提供了类似EJB的

spring in action学习笔记十五:配置DispatcherServlet和ContextLoaderListener的几种方式。

在spring in action中论述了:DispatcherServlet和ContextLoaderListener的关系,简言之就是DispatcherServlet是用于加载web层的组件的上下文.ContextLoadListener是加载 其他组件的上下文. 第一种方式:纯注解的方式: 在spring4.0版本以上,倾向用注解的方式配置DispatcherServlet和ContextLoaderListener.配置方式如下: 思路:一个类只要继承AbstractAnnotati

spring in action学习笔记十六:配置数据源的几种方式

第一种方式:JNDI的方式. 用xml配置的方式的代码如下: 1 <jee:jndi-lookup jndi-name="/jdbc/spittrDS" resource-ref="true" id="dataSource"/> 用注解方式的代码如下: 1 @Bean 2 public JndiObjectFactoryBean jndiObjectFactoryBean(){ 3 JndiObjectFactoryBean jndi

Spring in Action 学习笔记三-AOP

面向切面的Spring 2015年10月9日 11:30 ? ? ? ? ? ? 屏幕剪辑的捕获时间: 2015-10-9 14:30 ? ? ? ? ? ? 屏幕剪辑的捕获时间: 2015-10-9 14:38 ? ? ? ? ? ? 屏幕剪辑的捕获时间: 2015-10-9 14:38 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 屏幕剪辑的捕获时间: 2015-10-10 14:42 ? ? ? ? ? ? ? ? ? 屏幕剪辑的捕获时间: 2015-10-10 14:43

spring in action学习笔记七:@Conditional注解的用法

@Profile注解是@Conditional注解的一个例子.即@Profile也是用@Conditional注解来实现的. 必须让条件实现Condition这个接口. 下面的案例讲如果环境中有magic这个属性,则能通过条件,spring会创建bean.反之如果环境中没有magic这个属性,则不能通过条件,spring就不会创建bean,会报错. 案例的代码如下: MagicBean的代码如下: 1 package com.advancedWiring.conditionalBeans; 2

spring in action 学习笔记九:如何证明在scope为prototype时每次创建的对象不同。

spring 中scope的值有四个:分别是:singleton.prototype.session.request.其中session和request是在web应用中的. 下面证明当scope为prototype时每次创建的对象是不同的. 示例代码如下: 1 package com.advancedWiring.ambiguityIniAutowiring2; 2 3 import org.springframework.beans.factory.BeanNameAware; 4 impor

spring in action 学习笔记十三:SpEL语言(Spring Expression Language)

SpEl语言的目的之一是防止注入外部属性的代码硬代码化.如@Value("#{student.name}")这个注解的意思是把Student类的name的属性值注入进去.其中student指向Student,是Student的id. SpEl的作用是: 1.The ability to reference beans by their IDs; 2.Invoking methods and accessing propeerties on objects 3.Mathmatical,r

spring in action 学习笔记八:用@Primary 或者@Qualifier消除@Autowired引起的歧义现象

首先解释一下@Primary和@Qualifier这两个注解的意思:@Primary的意思是在众多相同的bean中,优先使用用@Primary注解的bean.而@Qualifier这个注解则指定某个bean有没有资格进行注入. 示例代码的思路是:1.一个接口Dessert和这个接口的三个实现类,2.再在一个类(AbrahamLincoln)中自动注入Dessert这个接口,3.用自动扫描机制自动创建bean. 如果不用@Primary和@Qualifier注解,势必出现如下错误:NoUnique