vlambda博客
学习文章列表

Spring浅入浅出—不吹牛逼不装逼


前言



又总结了点框架,虽然以前总结过两篇,但是思维是变化的,而且也没有什么规定说总结过的东西就不能再总结了,是吧。这次总结我命名为浅入浅出,主要在于理解框架核心,轻松愉快使用框架。



核心思想



我们都学了面向对象,在生活中,当人们需要一件东西时,第一反应就是找东西,例如想吃面包,现在有两种情况,第一种是没有面包店,第二种是有面包店。第一种情况就是我们之前一直遇到的情况,在没有面包店的情况下,最直观的做法可能就是你按照自己的口味制作面包,也就是一个面包需要主动制作,谁想吃了就自己New。而我主要说的是第二种情况,就是有面包店,你想吃面包的时候找到面包店,把自己的口味告诉店家,店家就可以给你做符合你口味的面包了。注意:你并没有制作面包,而是由店家制作,但是完全符合你的口味。


这是一个很生活的例子,大家都明白,但这里包含了Spring中很重要的思想——控制反转,就是把制作面包的主动权交给店家,面包就是对象,店家相当于一个大容器,你想要什么对象,就让大容器去给你生产,这就是控制反转思想。


再详细点,当某个Java对象(调用者,例如你)需要调用另一个Java对象(被调用者,即被依赖对象,例如面包)时,在传统编程模式下,调用者通常会采用“New 被调用者”的代码方式来创建对象(例如你自己制作面包)。这种方式会增加调用者与被调用者之间的耦合性,不利于后期代码的升级和维护。


当Spring框架出现后,对象的实例不再由调用者来创建,而是由 Spring容器(例如面包店)来创建。Spring容器会负责控制程序之间的关系(例如面包店负责控制你与面包的关系),而不是由调用者的程序代码直接控制。这样,控制权由调用者转移到Spring容器,控制权发生了反转,这就是Spring的控制反转。


在之前,我们需要用构造方法或者set()方法给一些成员变量赋值,从Spring容器角度来看,Spring容器负责将被依赖对象赋值给调用者的成员变量,相当于为调用者注入它所依赖的实例,这就是Spring的依赖注入。


综上所述,控制反转是一种通过描述(在Spring中可以是XML或注解)并通过第三方去产生或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入。



Spring IoC容器



看完上面所述,我们知道实现控制反转的是Spring IoC容器。Spring IoC容器的设计主要是基于BeanFactory和ApplicationContext两个接口。


先说BeanFactory,它提供了完整的IoC服务支持,是一个管理Bean的工厂,主要负责初始化各种Bean。BeanFactory接口有多个实现类,其中比较常用的是org.springframework.beans.factory.xml.XmlBeanFactory,该类会根据XML配置文件中的定义来装配Bean.由于BeanFactory实例加载Spring配置文件在实际开发中并不多见,只需了解即可,我也不过多解说了。


再说ApplicationContext,它是BeanFactory的子接口,也称为应用上下文,ApplicationContext接口除了包含BeanFactory的所有功能以外,还添加了对国际化、资源访问、事件传播等内容的支持。创建ApplicationContext接口实例通常有三种方法:

1、 通过ClassPathXmlApplicationContext创建

2、 通过FileSystemXmlApplicatonContext创建

3、 通过Web服务器实例化ApplicationContext容器


作为一个初学者,我觉得先会用第一种就可以了,所以我主要解说第一种,别的等你自己入门后自己看,我只做引导。


ClassPathXmlApplicationContext将从类路径目录(src根目录)中寻找指定的XML配置文件,如下代码:


 
   
   
 
  1. public class Test {

  2. public static void main(String[] args) {

  3. //初始化SPring容器,加载配置文件

  4. ApplicationContext appCon = new ClassPathXmlApplicationContext("spring-config.xml");

  5. //通过容器获得test实例

  6. TestDao tt = (TestDao) appCon.getBean("test");

  7. tt.sayHello();

  8. }

  9. }




依赖注入的类型



在Spring中实现IoC容器的方法是依赖注入,依赖注入的作用是在使用Spring框架创建对象时动态地将其所依赖的对象(例如属性值)注入Bean组件中,Spring框架的依赖注入通常有两种实现方式,一种是使用构造方法注入,另一种是使用属性的setter方法注入。具体且看实例演示

实例演示

1、 在pom.xml中导入相应模块

 
   
   
 
  1. <dependencies>

  2. <dependency>

  3. <groupId>junit</groupId>

  4. <artifactId>junit</artifactId>

  5. <version>4.11</version>

  6. <scope>test</scope>

  7. </dependency>

  8. <dependency>

  9. <groupId>javax.servlet</groupId>

  10. <artifactId>javax.servlet-api</artifactId>

  11. <version>3.1.0</version>

  12. </dependency>

  13. <dependency>

  14. <groupId>javax.servlet</groupId>

  15. <artifactId>jstl</artifactId>

  16. <version>1.2</version>

  17. </dependency>

  18. <dependency>

  19. <groupId>commons-logging</groupId>

  20. <artifactId>commons-logging</artifactId>

  21. <version>1.2</version>

  22. </dependency>


  23. <!--spring核心依赖-->

  24. <dependency>

  25. <groupId>mysql</groupId>

  26. <artifactId>mysql-connector-java</artifactId>

  27. <version>5.1.38</version>

  28. </dependency>

  29. <dependency>

  30. <groupId>org.springframework</groupId>

  31. <artifactId>spring-beans</artifactId>

  32. <version>5.1.5.RELEASE</version>

  33. </dependency>

  34. <dependency>

  35. <groupId>org.springframework</groupId>

  36. <artifactId>spring-context</artifactId>

  37. <version>5.1.5.RELEASE</version>

  38. </dependency>

  39. <dependency>

  40. <groupId>org.springframework</groupId>

  41. <artifactId>spring-aop</artifactId>

  42. <version>5.1.5.RELEASE</version>

  43. </dependency>

  44. <dependency>

  45. <groupId>org.springframework</groupId>

  46. <artifactId>spring-jdbc</artifactId>

  47. <version>5.1.5.RELEASE</version>

  48. </dependency>

  49. <dependency>

  50. <groupId>org.springframework</groupId>

  51. <artifactId>spring-web</artifactId>

  52. <version>5.1.5.RELEASE</version>

  53. </dependency>

  54. <dependency>

  55. <groupId>org.springframework</groupId>

  56. <artifactId>spring-webmvc</artifactId>

  57. <version>5.1.5.RELEASE</version>

  58. </dependency>

  59. <dependency>

  60. <groupId>org.springframework</groupId>

  61. <artifactId>spring-expression</artifactId>

  62. <version>5.1.5.RELEASE</version>

  63. </dependency>

  64. <dependency>

  65. <groupId>org.springframework</groupId>

  66. <artifactId>spring-tx</artifactId>

  67. <version>5.1.5.RELEASE</version>

  68. </dependency>


  69. </dependencies>


2、 创建TestDao

 
   
   
 
  1. package com.my.dao;


  2. public interface TestDao {

  3. public void sayHello();

  4. }


3、 创建TestDaoImpl


 
   
   
 
  1. package com.my.dao.impl;


  2. import com.my.dao.TestDao;


  3. public class TestDaoImpl implements TestDao {

  4. @Override

  5. public void sayHello() {

  6. System.out.println("Hello Spring!!!");

  7. }

  8. }


4、 创建spring-config.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. xmlns:context="http://www.springframework.org/schema/context"

  5. xmlns:tx="http://www.springframework.org/schema/tx"

  6. xmlns:mvc="http://www.springframework.org/schema/mvc"

  7. xsi:schemaLocation="http://www.springframework.org/schema/beans

  8. http://www.springframework.org/schema/beans/spring-beans.xsd

  9. http://www.springframework.org/schema/context

  10. http://www.springframework.org/schema/context/spring-context.xsd

  11. http://www.springframework.org/schema/tx

  12. http://www.springframework.org/schema/tx/spring-tx.xsd

  13. http://www.springframework.org/schema/mvc

  14. http://www.springframework.org/schema/mvc/spring-mvc.xsd

  15. ">

  16. <bean id="testDIDao" class="com.my.dao.impl.TestDaoImpl"/>

  17. </beans>


5、 测试Test


 
   
   
 
  1. package com.my.test;


  2. import com.my.dao.TestDao;

  3. import com.my.dao.impl.TestDaoImpl;

  4. import com.my.service.TestService;

  5. import org.springframework.context.ApplicationContext;

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


  7. public class Test {

  8. public static void main(String[] args) {

  9. //调用者自己创建对象

  10. TestDao testDao = new TestDaoImpl();

  11. testDao.sayHello();


  12. //初始化SPring容器,加载配置文件

  13. ApplicationContext appCon = new ClassPathXmlApplicationContext("spring-config.xml");

  14. //通过容器获得test实例

  15. TestDao tt = (TestDao) appCon.getBean("testDIDao");

  16. tt.sayHello();


  17. }

  18. }


6、 测试结果



7、 创建TestService


 
   
   
 
  1. package com.my.service;


  2. public interface TestService {

  3. public void sayHello();

  4. }


8、 创建TestServiceImpl

 
   
   
 
  1. package com.my.service.impl;


  2. import com.my.dao.TestDao;

  3. import com.my.service.TestService;


  4. public class TestServiceImpl implements TestService {

  5. private TestDao testDao;

  6. //构造方法,用于实现依赖注入接口对象TestDao

  7. public TestServiceImpl(TestDao testDao) {

  8. this.testDao = testDao;

  9. }


  10. @Override

  11. public void sayHello() {

  12. testDao.sayHello();

  13. }

  14. }


9、 在spring-config.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. xmlns:context="http://www.springframework.org/schema/context"

  5. xmlns:tx="http://www.springframework.org/schema/tx"

  6. xmlns:mvc="http://www.springframework.org/schema/mvc"

  7. xsi:schemaLocation="http://www.springframework.org/schema/beans

  8. http://www.springframework.org/schema/beans/spring-beans.xsd

  9. http://www.springframework.org/schema/context

  10. http://www.springframework.org/schema/context/spring-context.xsd

  11. http://www.springframework.org/schema/tx

  12. http://www.springframework.org/schema/tx/spring-tx.xsd

  13. http://www.springframework.org/schema/mvc

  14. http://www.springframework.org/schema/mvc/spring-mvc.xsd

  15. ">

  16. <!--将指定类TestDaoImpl配置给Spring,让Spring创建其实例-->

  17. <bean id="testDIDao" class="com.my.dao.impl.TestDaoImpl"/>

  18. <!--使用构造方法注入-->

  19. <bean id="testDIService" class="com.my.service.impl.TestServiceImpl" >

  20. <!--将TestDIDao注入到TestDIServiceImpl类的属性testDao上-->

  21. <constructor-arg index="0" ref="testDIDao"/>

  22. </bean>

  23. </beans>


10、 测试Test


 
   
   
 
  1. package com.my.test;


  2. import com.my.dao.TestDao;

  3. import com.my.dao.impl.TestDaoImpl;

  4. import com.my.service.TestService;

  5. import org.springframework.context.ApplicationContext;

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


  7. public class Test {

  8. public static void main(String[] args) {

  9. //调用者自己创建对象

  10. TestDao testDao = new TestDaoImpl();

  11. testDao.sayHello();


  12. //初始化SPring容器,加载配置文件

  13. ApplicationContext appCon = new ClassPathXmlApplicationContext("spring-config.xml");

  14. //通过容器获得test实例

  15. TestDao tt = (TestDao) appCon.getBean("testDIDao");

  16. tt.sayHello();

  17. //通过容器获取TestService实例,测试构造方法注入

  18. TestService testService =(TestService) appCon.getBean("testDIService");

  19. testService.sayHello();

  20. }

  21. }


11、测试结果


Spring浅入浅出—不吹牛逼不装逼


12、使用属性的setter方法注入


 
   
   
 
  1. package com.my.service.impl;


  2. import com.my.dao.TestDao;

  3. import com.my.service.TestService;


  4. public class TestServiceImpl implements TestService {

  5. private TestDao testDao;


  6. //添加testDao属性的setter方法,用于实现依赖注入

  7. public void setTestDao(TestDao testDao){

  8. this.testDao=testDao;

  9. }


  10. @Override

  11. public void sayHello() {

  12. testDao.sayHello();

  13. }

  14. }


13、在spring-config.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. xmlns:context="http://www.springframework.org/schema/context"

  5. xmlns:tx="http://www.springframework.org/schema/tx"

  6. xmlns:mvc="http://www.springframework.org/schema/mvc"

  7. xsi:schemaLocation="http://www.springframework.org/schema/beans

  8. http://www.springframework.org/schema/beans/spring-beans.xsd

  9. http://www.springframework.org/schema/context

  10. http://www.springframework.org/schema/context/spring-context.xsd

  11. http://www.springframework.org/schema/tx

  12. http://www.springframework.org/schema/tx/spring-tx.xsd

  13. http://www.springframework.org/schema/mvc

  14. http://www.springframework.org/schema/mvc/spring-mvc.xsd

  15. ">

  16. <!--将指定类TestDaoImpl配置给Spring,让Spring创建其实例-->

  17. <bean id="testDIDao" class="com.my.dao.impl.TestDaoImpl"/>


  18. <!--使用setter方法注入-->

  19. <bean id="testDIService" class="com.my.service.impl.TestServiceImpl">

  20. <!--调用TestDIServiceImpl类的setter方法,将TestDao注入到TestServiceImpl类的属性testDao上-->

  21. <property name="testDao" ref="testDIDao"></property>

  22. </bean>

  23. </beans>


14、测试Test


 
   
   
 
  1. package com.my.test;


  2. import com.my.dao.TestDao;

  3. import com.my.dao.impl.TestDaoImpl;

  4. import com.my.service.TestService;

  5. import org.springframework.context.ApplicationContext;

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


  7. public class Test {

  8. public static void main(String[] args) {

  9. //调用者自己创建对象

  10. TestDao testDao = new TestDaoImpl();

  11. testDao.sayHello();


  12. //初始化SPring容器,加载配置文件

  13. ApplicationContext appCon = new ClassPathXmlApplicationContext("spring-config.xml");

  14. //通过容器获得test实例

  15. TestDao tt = (TestDao) appCon.getBean("testDIDao");

  16. tt.sayHello();

  17. //通过容器获取TestService实例,测试setter方法注入

  18. TestService testService =(TestService) appCon.getBean("testDIService");

  19. testService.sayHello();

  20. }

  21. }


15、测试结果


Spring浅入浅出—不吹牛逼不装逼



注入说明



在Src根目录下创建Spring配置文件spring-config.xml(文件名随意,注意后缀.xml)。在配置文件中,constructor-arg元素用于定义类构造方法的参数,index用于定义参数的位置,ref指定某个实例的引用,如果参数是常量值,ref由value代替。



特别链接



看完此篇后你觉得理解了,可以看看我以前写的这几篇博客,会有帮助的

《没有无缘无故的编程》https://www.cnblogs.com/zyx110/p/11297822.html

《路过别错过》https://www.cnblogs.com/zyx110/p/11271820.html

《spring框架知多少》https://www.cnblogs.com/zyx110/p/11022891.html

《用IDEA开发Spring程序》https://www.cnblogs.com/zyx110/p/11023218.html



结束语



此篇Spring浅入浅出到此结束,作此篇是为了让初学者放下心理枷锁,先理解,其实挺好理解的,等你有信心后自己学习就可以了,希望能对一些朋友有所帮助,加油。


Spring浅入浅出—不吹牛逼不装逼


往期推荐

  • 《》

  • 《》

  • 《》

  • 《》

  • 《》

  • 《》

  • 《》

  • 《》

  • 《》

  • 《》

长按扫码关注

等风也等你

点击阅读原文,进入我的博客