Spring学习小记(三)

67 篇文章 0 订阅
Spring IoC入门
 
本小记中学习的目标
  1. Spring IoC的基本概念的理解
  2. Spring IoC容器的理解
  3. 依赖注入的类型(构造方法、setter方法)的实现方法
 
一、Spring IoC的基本概念
IoC:Inversion of Control,控制反转,它是Spring框架的核心,目的是用来减少程序模块间的耦合问题。
DI:Dependency Injection,依赖注入,它是IoC的另一种说法。
    在Java编程中,如果某个对象,需要调用另一个对象(这个对象被称作为被依赖对象)时,首先我们想到的最为直观简单的编程方式就是使用【new 被调用者】的方式来创建对象。这种方式可以满足当前的即时需求,但是在未来一但被调用者升级修改了有可能影响到new的方式,这样就增加了调用者与被调用者之间的耦合性。
    说完上面的例子看到了它不友好的一面,那Spring框架出来后在这个方面为程序员提供了更好的解决方案,这个时候被调用者的对象实例并不是由调用者自行来new出来,而是由Spring容器来创建。Spring容器会控制调用者与被调用者的关系,把这种关系的控制由原来的调用者使用代码控制变为交由Spring容器来控制,这种控制权发生了相应的转换,这也就是Spring的控制反转。
    说到这里,Spring容器的任务就是把被依赖的对象赋值给调用者的成员变量,相当于为调用者注入它依赖的对象,这也就是Spring的依赖注入。
 
Spring IoC
    理解一下Spring IoC容器设计的实现
    它的实现主要依赖于如下两个接口:BeanFactory、ApplicationContext
    BeanFactory接口    org.springframework.beans.factory.BeanFactory
    从这个接口的命名可以看出来它是一个管理Bean的工厂,它的工作就是初始化各种Bean。
    ApplicationContext接口    org.springframework.context.ApplicationContext    (常用重要)
    这个接口除了有BeanFactory接口的所有功能外,还额外添加了对国际化、资源访问、事件传播……的支持。
    创建ApplicationContext接口实例的三种方式
    方式一:使用ClassPathXmlApplicationContext创建
    从这个实现的命名可以看出,这会从classpath路径(类路径,src根目录,maven工程中src/main/resources)中查找指定的xml配置文件
    方式二:FileSystemXmlApplicationContext创建(一般不使用这种方式)
    从这个实现的命名可以看出,它会从指定文件的绝对路径中查找xml配置文件
    方式三:通过Web服务器实例化ApplicationContext容器(原理:在服务器加载时使用监听器完成)
    一般是使用org.springframework.web.context.ContextLoaderListener的实现方式,这种方式需要依赖spring-web-xxx.RELEASE.jar,同时需要在web.xml中做如下配置
<!-- 配置ContextLoaderListener,用来初始化spring的配置文件 -->
       < context-param >
             < param-name >contextConfigLocation </ param-name >
             < param-value >classpath:beans.xml </ param-value >
       </ context-param >
       < listener >
             < listener-class >org.springframework.web.context.ContextLoaderListener </ listener-class >
       </ listener >
一旦我们有了配置的信息并交给Spring后,Spring就知道如何把被依赖的对象注入到调用者当中,这样就不再需要通过程序new的方式来操作了
 
依赖注入类型
Spring IoC是通过依赖注入的方式来实现的,它的作用是在使用Spring框架创建对象时动态地把依赖的对象注入bean组件中。Spring框架的依赖注入主要有两种实现方式,一种是通过构造方法来实现;另一种是通过setter方法来注入
构造方法注入
构造方法的注入方式是Spring采用了Java反射的机制来完成的。
实例
1.新增一个Maven的jar工程
2.在pom.xml中新增如下依赖
< dependencies >
       <!-- 添加Spring核心依赖包 Context -->
       < dependency >
             < groupId >org.springframework </ groupId >
             < artifactId >spring-context </ artifactId >
             < version >5.0.2.RELEASE </ version >
       </ dependency >
       <!-- commons-logging-1.2 -->
       < dependency >
       < groupId >commons-logging </ groupId >
       < artifactId >commons-logging </ artifactId >
       < version >1.2 </ version >
       </ dependency >     
  </ dependencies >
3.新增一个Dao接口
com.xiaoxie.dao.TestDIDao
在其中新增一个接口方法
package com.xiaoxie.dao;
public interface TestDIDao {
       void sayHello();
}
4.新增TestDIDao的实现类
com.xiaoxie.dao.impl.TestDIDaoImpl
package com.xiaoxie.dao.impl;
import com.xiaoxie.dao.TestDIDao;
public class TestDIDaoImpl implements TestDIDao {
       @Override
       public void sayHello() {
            System. out.println( "sayHello()方法输出:DI注入类型-构造方法");
      }
}
5.新增service包并在其中新增Service的接口
package com.xiaoxie.service;
public interface TestDIService {
       void sayHello();
}
6.新增service的实现包impl,并在其中新增TestDIService的实现类,并把Dao包中的实例对象做注入
package com.xiaoxie.service.impl;
import com.xiaoxie.dao.TestDIDao;
import com.xiaoxie.service.TestDIService;
public class TestDIServiceImpl implements TestDIService {
       private TestDIDao testDIDao;
      
       //构造方法,用来注入TestDIDao的实例对象
       public TestDIServiceImpl(TestDIDao testDIDao) {
            System. out.println( "调用TestDIServiceImpl构造函数!");
             this. testDIDao = testDIDao;
            System. out.println( "构造函数调用完成,testDIDao被赋值:" + testDIDao);
      }
      
       @Override
       public void sayHello() {
             //调用testDIDao中的sayHello方法
             testDIDao.sayHello();
      }
}
7.在src/main/resources下新增Spring配置文件beans.xml
<? xml version= "1.0" encoding= "UTF-8" ?>
       xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
       <!-- 把 Dao 的实现类交由Spring容器进行管理,让Spring来创建它 -->
       < bean class= "com.xiaoxie.dao.impl.TestDIDaoImpl" id= "testDIDao" />
       <!-- 在Service中使用构造方法进行注入依赖有对象 -->
       < bean class= "com.xiaoxie.service.impl.TestDIServiceImpl" id= "testDIService" >
             < constructor-arg name= "testDIDao" ref= "testDIDao" />
       </ bean >
</ beans >
在上面的配置中我们可以看到在将TestDIServiceImpl交由Spring管理时,同时使用了<constructor-arg>标签来对其构造函数中属性进行实参传递以达到初始化它依赖对象的目的
8.创建测试包及测试类
在src/test/java中新增测试包及测试类如下
package com.xiaoxie.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.xiaoxie.service.TestDIService;
public class TestDI {
       public static void main(String[] args) {
             //加载Spring配置文件初始化Spring容器
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext( "beans.xml");
             TestDIByConstruct( applicationContext);
      }
      
       private static void TestDIByConstruct(ApplicationContext applicationContext) {
            TestDIService testDIService = (TestDIService) applicationContext.getBean( "testDIService");
             testDIService.sayHello();
      }
}
在上面的测试代码中我们可以看到在根据Spring配置文件初始化Spring容器后,获取Spring配置文件所指定的testDIService这个id指定的实例对象,同时这个时候会把其依赖的对象也初始化好。
9.运行测试类,在控制台打印的结果如下:
调用TestDIServiceImpl构造函数!
构造函数调用完成,testDIDao被赋值:com.xiaoxie.dao.impl.TestDIDaoImpl@77f80c04
sayHello()方法输出:DI注入类型-构造方法
 
属性setter方法注入
使用setter方法注入,Spring也是使用了Java的反射机制,它是Spring框架中常用的注入方法,利用Java Bean的setter方法来完成注入。
实例
1.在Dao的接口中新增接口方法sayHello1()
package com.xiaoxie.dao;
public interface TestDIDao {
       void sayHello();
       void sayHello1();
}
2.在Dao的接口实现类中添加sayHello1()的实现方法
package com.xiaoxie.dao.impl;
import com.xiaoxie.dao.TestDIDao;
public class TestDIDaoImpl implements TestDIDao {
       @Override
       public void sayHello() {
            System. out.println( "sayHello()方法输出:DI注入类型-构造方法");
      }
      
       @Override
       public void sayHello1() {
            System. out.println( "sayHello()方法输出:DI注入类型-setter方法");
      }
}
3.在service接口中新增接口方法sayHello1()
package com.xiaoxie.service;
public interface TestDIService {
       void sayHello();
       void sayHello1();
}
4.修改TestDIServiceImpl类的实现如下
package com.xiaoxie.service.impl;
import com.xiaoxie.dao.TestDIDao;
import com.xiaoxie.service.TestDIService;
public class TestDIServiceImpl implements TestDIService {
       private TestDIDao testDIDao;
      
       //构造方法,用来注入TestDIDao的实例对象
       public TestDIServiceImpl(TestDIDao testDIDao) {
            System. out.println( "调用TestDIServiceImpl构造函数!");
             this. testDIDao = testDIDao;
            System. out.println( "构造函数调用完成,testDIDao被赋值:" + testDIDao);
      }
      
       @Override
       public void sayHello() {
             //调用testDIDao中的sayHello方法
             testDIDao.sayHello();
      }
       @Override
       public void sayHello1() {
      }
}
5.在上面的工程中新增一个service实现类,在这个实现类中我们计划使用setter方法来做注入
package com.xiaoxie.service.impl;
import com.xiaoxie.dao.TestDIDao;
import com.xiaoxie.service.TestDIService;
public class TestDIServiceImpl1 implements TestDIService {
       private TestDIDao tesDIDao1;
       //setter方法
       public void setTesDIDao1(TestDIDao tesDIDao1) {
            System. out.println( "调用setter方法");
             this. tesDIDao1 = tesDIDao1;
            System. out.println( "setter方法调用完成,testDIDao1对象:" + tesDIDao1);
      }
       @Override
       public void sayHello1() {
             tesDIDao1.sayHello1();
      }
       @Override
       public void sayHello() {
      }
}
6.Spring容器的配置文件中新增内容后如下
<? xml version= "1.0" encoding= "UTF-8" ?>
       xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
       <!-- 把 Dao 的实现类交由Spring容器进行管理,让Spring来创建它 -->
       < bean class= "com.xiaoxie.dao.impl.TestDIDaoImpl" id= "testDIDao" />
       <!-- 在Service中使用构造方法进行注入依赖有对象 -->
       < bean class= "com.xiaoxie.service.impl.TestDIServiceImpl" id= "testDIService" >
             < constructor-arg name= "testDIDao" ref= "testDIDao" />
       </ bean >
       <!-- 在Service中使用setter方法进行注入依赖的对象 -->
       < bean class= "com.xiaoxie.service.impl.TestDIServiceImpl1" id= "testDIService1" >
             < property name= " tesDIDao1" ref= "testDIDao" ></ property >
       </ bean >
</ beans >
7.在测试类中测试方法中新增测试方法及在main方法中对方法进行调用
package com.xiaoxie.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.xiaoxie.service.TestDIService;
public class TestDI {
       public static void main(String[] args) {
             //加载Spring配置文件初始化Spring容器
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext( "beans.xml");
             TestDIByConstruct( applicationContext);
            System. out.println( "--------setter方法进行注入-------");
             TestDIBySetter( applicationContext);
      }
      
       private static void TestDIByConstruct(ApplicationContext applicationContext) {
            TestDIService testDIService = (TestDIService) applicationContext.getBean( "testDIService");
             testDIService.sayHello();
      }
      
       public static void TestDIBySetter(ApplicationContext applicationContext) {
            TestDIService testDIService = (TestDIService) applicationContext.getBean( "testDIService1");
             testDIService.sayHello1();
      }
}
8.运行测试类,在控制台打印结果如下
调用TestDIServiceImpl构造函数!
构造函数调用完成,testDIDao被赋值:com.xiaoxie.dao.impl.TestDIDaoImpl@38e79ae3
调用setter方法
setter方法调用完成,testDIDao1对象:com.xiaoxie.dao.impl.TestDIDaoImpl@38e79ae3
sayHello()方法输出:DI注入类型-构造方法
--------setter方法进行注入-------
sayHello()方法输出:DI注入类型-setter方法
 
从上面打印的结果可以看到,在使用Spring配置文件初始化Spring容器时Spring就会把依赖全部做完,且它默认是一个单例的方式进行的注入
 
 
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值