Spring核心概念

Spring IoC

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

  依赖是什么:

      依赖就是在代码中通过局部变量、方法参数、返回值等建立的对于其他对象的调用关系。

 1 /**
 2  * @content 接口
 3  * @author Gawain
 4  * @date 2017-8-15下午8:02:37
 5  */
 6 public interface DependDemo {
 7     /**
 8      * 显示信息
 9      */
10     void showInfo();
11 }
12
13 /**
14  * @content 实现类
15  * @author Gawain
16  * @date 2017-8-15下午8:02:30
17  */
18 public class DependDemoImpl implements DependDemo {
19     /**
20      * 实现方法
21      */
22     @Override
23     public void showInfo() {
24         System.out.println("你好");
25     }
26 }
27
28 /**
29  * @content 测试类
30  * @author Gawain
31  * @date 2017-8-15下午8:02:09
32  */
33 public class Demo {
34     public static void main(String[] args) {
35         //实例化依赖的对象,此时,Demo类依赖于DependDemoImpl类
36         DependDemo demo = new DependDemoImpl();
37         //调用方法
38         demo.showInfo();
39     }
40 }

例子

      通过上面的代码可以看出,Demo类和DependDemoImpl类高度耦合,如果需求变化需要替换DependDemo接口的实现类DependDemoImpl的话,那么Demo中的代码也需要进行改动。

  解决方法(控制反转):

      创建一个对象工厂,将创建实例的工作交给工厂去做,获得对象时不通过new的方式而是通过工厂来获得对象。

 1 /**
 2  * @content 对象工厂
 3  * @author Gawain
 4  * @date 2017-8-15下午8:11:27
 5  */
 6 public class Factory {
 7     /**
 8      * 返回对象实例
 9      * @return
10      */
11     public static DependDemo getDepend() {
12         return new DependDemoImpl();
13     }
14 }
15
16 /**
17  * @content 测试类
18  * @author Gawain
19  * @date 2017-8-15下午8:02:09
20  */
21 public class Demo {
22     public static void main(String[] args) {
23         //通过对象工厂获得实例
24         DependDemo demo = Factory.getDepend();
25         //调用方法
26         demo.showInfo();
27     }
28 }

工厂例子

      通过上面的代码可以看出,Demo类不再依靠自身的代码去获得所依赖的具体的DependDemo对象,而是将这一工作交给了对象工厂去做,如果DependDemo接口的实现类需要替换的话,只要在工厂类修改代码即可。此时由工厂来控制创建对象而不是Demo本身,这就是控制反转。

      按照上面的方法虽然可以解决问题,但是大量的工厂类会被引入到开发过程中,大大的增加了开发的工作量。此时我们就需要用到Spring了。

      Spring为我们提供了完整的IoC实现,让我们得以专注于业务类和DAO类的设计。

开发Spring项目

  1.下载Spring的jar包并添加到项目中。也可以使用MyEclipse来简化这一步骤。右击项目,选择MyEclipse-->Add Spring Capabilities...然后直接点击Finish。

      

  2.编写Spring配置文件

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans
 3     xmlns="http://www.springframework.org/schema/beans"
 4     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 5     xmlns:p="http://www.springframework.org/schema/p"
 6     xsi:schemaLocation="http://www.springframework.org/schema/beans
 7     http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
 8     <!-- 通过bean元素声明需要Spring创建的实例。该实例的类型通过class属性指定,并通过id属性为该实例指定一个名称,以便于访问 -->
 9     <bean id="dependDemo" class="com.jazz.demo.DependDemoImpl"/>
10 </beans>

applicationContext.xml配置文件

      补充:

          1.applicationContext.xml是MyEclipse自动帮你添加的。如果你是自己导的jar包的话,这一文件需自己手动创建。

          2.上述代码中的id属性也可以使用name属性来完成相同的工作。二者的不同之处在于id属性只能指定一个名称,而name属性可以指定多个名称,多个名称之间使用空格或者逗号隔开。

          3.class属性是类的全限定类名。

  3.编写代码通过Spring获取DependDemo实例

 1 import org.springframework.context.ApplicationContext;
 2 import org.springframework.context.support.ClassPathXmlApplicationContext;
 3
 4 /**
 5  * @content 测试类
 6  * @author Gawain
 7  * @date 2017-8-15下午8:02:09
 8  */
 9 public class Demo {
10     public static void main(String[] args) {
11         //通过ClassPathXmlApplicationContext实例化Spring的上下文
12         ApplicationContext con = new ClassPathXmlApplicationContext("applicationContext.xml");
13         //通过ApplicationContext的getBean()方法根据id来获取bean的实例
14         DependDemo demo = con.getBean("dependDemo", DependDemoImpl.class);
15         //调用方法
16         demo.showInfo();
17     }
18 }

通过SpringIoC容器获取对象实例

      补充:

          1.在上面的代码中,ApplicationContext是一个接口,负责读取Spring配置文件,管理对象的加载、生成,维护Bean对象与Bean对象之间的依赖关系,负责Bean的生命周期等。

           2.ClassPathXmlApplicationContext是ApplicationContext接口的实现类,用于从classpath路径中读取Spring配置文件。classpath路径就是src文件夹。

           3.写在配置文件中的Bean会在ClassPathXmlApplicationContext加载Spring配置文件时创建生成。

小结:

  Spring IoC它就是一个容器,负责管理Bean的创建以及管理Bean与Bean之间的关系等等。


依赖注入

  依赖注入是什么?

      依赖注入就是将Bean的创建以及为属性赋值的工作交给Spring容器来做,从而避免组件之间以硬编码的方式耦合在一起。

   上文提到过,Spring IoC不仅可以管理对象的加载与生成,还可以管理Bean与Bean之间的依赖关系。除此之外,还可以在创建Bean时为Bean中的属性赋初值。

  下面再写一个小例子演示一下依赖注入。

 1 /**
 2  * @content 书实体类
 3  * @author Gawain
 4  * @date 2017-8-15下午9:16:43
 5  */
 6 public class Book {
 7     //书籍名称
 8     private String bookName;
 9     //重写toString方法
10     @Override
11     public String toString() {
12         return "Book [bookName=" + bookName + "]";
13     }
14
15     public String getBookName() {
16         return bookName;
17     }
18
19     public void setBookName(String bookName) {
20         this.bookName = bookName;
21     }
22 }
23
24
25 /**
26  * @content 用户实体类
27  * @author Gawain
28  * @date 2017-8-15下午9:15:52
29  */
30 public class User {
31     //姓名
32     private String name;
33     //年龄
34     private int age;
35     //正在读的书籍
36     private Book book;
37     //重写toString方法
38     @Override
39     public String toString() {
40         return "User [name=" + name + ", age=" + age + ", book=" + book + "]";
41     }
42     public String getName() {
43         return name;
44     }
45     public void setName(String name) {
46         this.name = name;
47     }
48     public int getAge() {
49         return age;
50     }
51     public void setAge(int age) {
52         this.age = age;
53     }
54     public Book getBook() {
55         return book;
56     }
57     public void setBook(Book book) {
58         this.book = book;
59     }
60 }

实体类

 1 /**
 2  * @content 业务逻辑层接口
 3  * @author Gawain
 4  * @date 2017-8-15下午9:13:48
 5  */
 6 public interface UserService {
 7     /**
 8      * 显示信息
 9      */
10     void showInfo();
11 }
12
13
14 /**
15  * @content 业务逻辑层实现类
16  * @author Gawain
17  * @date 2017-8-15下午9:39:25
18  */
19 public class UserServiceImpl implements UserService {
20     private User user;
21     public User getUser() {
22         return user;
23     }
24     public void setUser(User user) {
25         this.user = user;
26     }
27     //显示用户信息
28     @Override
29     public void showInfo() {
30         System.out.println(user);
31     }
32 }

业务逻辑层

 1 /**
 2  * @content user控制层,此处作为测试类
 3  * @author Gawain
 4  * @date 2017-8-15下午9:31:35
 5  */
 6 public class UserController {
 7     public static void main(String[] args) {
 8         ApplicationContext con = new ClassPathXmlApplicationContext("applicationContext.xml");
 9         UserService userService = con.getBean("userService", UserServiceImpl.class);
10         userService.showInfo();
11     }
12 }

测试

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans
 3     xmlns="http://www.springframework.org/schema/beans"
 4     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 5     xmlns:p="http://www.springframework.org/schema/p"
 6     xsi:schemaLocation="http://www.springframework.org/schema/beans
 7     http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
 8     <!-- 通过bean元素声明需要Spring创建的实例。该实例的类型通过class属性指定,并通过id属性为该实例指定一个名称,以便于访问 -->
 9     <bean id="dependDemo" class="com.jazz.demo.DependDemoImpl"/>
10     <!-- 声明book对象 -->
11     <bean id="book" class="com.jazz.pojo.Book">
12         <!-- 为属性赋值 -->
13         <property name="bookName" value="Java数据结构和算法" />
14     </bean>
15     <!-- 声明user对象 -->
16     <bean id="user" class="com.jazz.pojo.User">
17         <property name="name" value="Gawain" />
18         <property name="age" value="18" />
19         <!-- 使用ref引用book对象,添加依赖关系 -->
20         <property name="book" ref="book" />
21     </bean>
22     <!-- 声明service对象 -->
23     <bean id="userService" class="com.jazz.services.impl.UserServiceImpl">
24         <property name="user" ref="user"/>
25     </bean>
26 </beans>

applicationContext.xml配置文件

      补充:

          1.为属性赋值的方式有很多种,除了上文的设值注入外,还有构造注入和p命名空间注入。

              构造注入语法:

                  <constructor-arg index="" value="" />

                  其中value是值,index是指构造方法中的第几个参数,从0开始。

              p命名空间注入语法:

 1 <beans xmlns="http://www.springframework.org/schema/beans"
 2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3 xmlns:p="http://www.springframework.org/schema/p"
 4 xsi:schemaLocation="http://www.springframework.org/schema/beans
 5 http://www.springframework.org/schema/beans/spring-beans.xsd">
 6 <bean name="john-classic" class="com.example.Person">
 7 <property name="name" value="John Doe"/>
 8 <property name="spouse" ref="jane"/>
 9 </bean>
10 <bean name="john-modern"
11 class="com.example.Person"
12 p:name="John Doe"
13 p:spouse-ref="jane"/>
14 <bean name="jane" class="com.example.Person">
15 <property name="name" value="Jane Doe"/>
16 </bean>
17 </beans>

p命名空间注入语法

                  使用p命名空间注入需要在beans中添加两个url,基本类型的属性使用p:属性名=属性值的方式注入,引用类型的属性使用p:属性名-ref=引用bean的id的方式注入。

          2.除了基本数据类型和自定义数据类型之外,Spring还支持很多数据类型,如下图所示。此处就不一一列举了。大家可以去Spring的帮助文档中查看。

              

              

小结:

  依赖注入其实就是将对象之间的依赖关系交给Spring来管理和组装了。不要看它名字说的很“高大上”,其实实现起来很简单。


Spring AOP

  Spring AOP简介:

      Spring AOP就是面向切面编程(Aspect Oriented Programming, AOP),是软件编程思想发展到一定阶段的产物,是面向对象编程(Object Oriented Programming, OOP)的有益补充。AOP一般适用于具有横切逻辑的场合,例如访问控制、事务管理、性能检测等。

  横切逻辑是什么:

      大家先来看一段代码

 1 public class UserController {
 2     //声明日志
 3     static Logger log = Logger.getLogger(UserController.class);
 4     public static void main(String[] args) {
 5         //在方法执行前输出日志
 6         log.info("显示用户信息");
 7         //使用try-catch来进行对异常的处理
 8         try {
 9             ApplicationContext con = new ClassPathXmlApplicationContext("applicationContext.xml");
10             UserService userService = con.getBean("userService", UserServiceImpl.class);
11             userService.showInfo();
12         } catch (Exception e) {
13             log.error("显示用户信息失败", e);
14         }
15     }
16 }

繁琐的代码

      上面的代码是一段典型的日志输出+异常处理的代码,从上面的代码可以看出,代码中添加了大量的日志和异常处理的代码,而我们实际的业务代码只有3行。

      日志、异常处理、事务控制是一个健壮的业务系统所必须的,但是为了保证系统健壮可用,就需要在众多的业务方法中“反复”编写类似的代码,使得原本就很复杂的业务处理代码变得更加复杂。

      在业务系统中,总有一些散落、渗透到系统各处且不得不处理的事情,这些穿插在既定业务中的操作就是所谓的“横切逻辑”,也被称为“切面”。

      面向切面编程极大的简化了上面代码中“重复”但又不得不写的代码,可以使我们在不改变原程序的基础上为代码段增加新的功能,对代码段进行增强处理。它的设计思想来源于代理设计模式。

  Spring AOP基本概念:

      1.切面(Aspect):一个模块化的横切逻辑(或横切关注点),可能会横切多个对象。

      2.连接点(Join Point):程序执行中的某个具体的执行点。

      3.增强处理(Advice):切面在某个特定连接点上执行的代码逻辑。

      4.切入点(Pointcut):对连接点的特征进行描述,可以使用正则表达式。增强处理和一个切入点表达式关联,并在与这个切入点匹配的某个连接点上运行。

      5.目标对象(Target object):被一个或多个切面增强的对象。

      6.AOP代理(AOP proxy):由AOP框架所创建的对象,实现执行增强处理方法等功能。

      7.织入(Weaving):将增强处理连接到应用程序中的类型或对象上的过程。

      8.增强处理类型:有前置增强、后置增强、环绕增强、异常抛出增强、最终增强等等。这些增强处理实现方式都差不多。



除了上文说的技术之外,spring的帮助文档也给我们提供了相当全面且详细的说明。

时间: 2024-10-01 02:43:20

Spring核心概念的相关文章

十分钟完成 spring 核心概念扫盲

一.背景 springframework 从 2.5 版本发展至今,期间已经发生了非常多的修正及优化.最初认为 spring 框架是一个非常轻量级的东西,轻量到你几乎认识不到必须使用它的理由.. 然而它又是那么的通用,几乎所有的流行框架如 持久层的 hibernate.表示层的 struts 都能跟它进行整合.但最终的结果是 spring 能整合的东西越来越多,逐渐的替代了其他的框架. 就比如 现在最火的 springboot,从Web控制层到持久层,任务调度.AOP 都已经被 spring 体

第一章 spring核心概念

一.Spring作用:管理项目中各种业务Bean(service类.Dao类.Action类),实例化类,属性赋值 二.Spring IOC(Inversion of Control )控制反转,也被称为依赖注入(Dependency Injection[DI]),是面向对象编程 中的一种设计理念,用来减轻程序代码之间的耦合度. IOC原理:侧重原理 在业务代码中不使用我们之间司空见惯的关键字new来构建一个业务实例,而是在配置文件中.通过xml节点来告知容器如何对内存中构建的对应类型的对象名称

Spring核心概念之AOP

一.AOP 的概念 AOP(Aspect Oriented Programming)的缩写,面向切面编程,主要作用就是对代码进行增强处理. 理解面向切面编程的含义:就是在不改变原有程序的基础上为代码增加新的功能. 实现面向切面编程需要了解两个概念: >切入点:可以插入增强处理的方法,比如原对象的fun()方法. >增强处理类型:在原对象fun()方法之前还是之后插入新功能. 二.Spring AOP简单应用 1.新建一个java项目 2.到官网下载Spring AOP和AspectJ框架所需要

Spring核心概念(二)

IOC/DI IOC(控制反转):对象(组件)的创建由代码中转移到外部容器(XML,注解) . DI(依赖注入):当类A需要使用类B时,那么我们需要为类A的属性赋值类B的对象. 这种现象我们称为依赖注入. 注意:IOC/DI指的是同一个东西,理解的角度不一样. 补充:组件化思想:分离关注点,使用接口,不再关注实现. AOP(面向切面编程) AOP:是一种通过预编译和运行期动态代理的方式实现在 不修改源代码的情况下给程序动态添加功能的技术. 原理: a.将复杂的需求分解出不同方面,将散布在系统中的

spring技术核心概念纪要

一.背景 springframework 从最初的2.5版本发展至今,期间已经发生了非常多的修正及优化.许多新特性及模块的出现,使得整个框架体系显得越趋庞大,同时也带来了学习及理解上的困难. 本文阐述了一些要点,并配合一些代码样例,这有助于快速理解 spring 框架. 二.spring架构 核心容器层 Core 模块 提供了框架的基本组成部分,包括 IoC 及依赖注入功能. Bean 模块 实现 Bean 管理,包括自动装配机制等功能: 其中BeanFactory是一个工厂模式的实现. Con

攻城狮在路上(贰) Spring(二)--- Spring IoC概念介绍

一.IoC的概念: IoC(控制反转)是Spring容器的核心.另一种解释是DI(依赖注入),即让调用类对某一个接口的依赖关系由第三方注入,以移除调用类对某一个接口实现类的一览. 定义如此,由此可见,在面向接口编程的情况下,IoC可以很好的实现解耦,可以以配置的方式为程序提供所需要的接口实现类. 在实际程序开发中,我们只需要提供对应的接口及实现类,然后通过Spring的配置文件或者注解完成对依赖类的装配.二.IoC的类型: 1.通过构造函数: 此种方式的缺点是,在构造函数中注入之后一般会作为一个

Spring核心学习-AOP(7) 织入和代理

前导:开始学习Spring核心思想,通过一个山寨精简版Spring代码结合学习. AdvisedSupport - 保存AOP配置 TargetSource - 保存被代理的数据 AopProxy - 对代理对象做代理,在调用目标方法前先调用它. JdkDynamicAopProxy - 使用JDK动态代理对接口做代理 ReflectiveMethodInvocation - 将反射的Method封装为Joinpoint MethodInterceptor - 对方法调用连接点实现包围通知的 A

从经典架构项目中透析微服务架构的核心概念和充血模型

微服务架构和SOA区别 微服务现在辣么火,业界流行的对比的却都是所谓的Monolithic单体应用,而大量的系统在十几年前都是已经是分布式系统了,那么微服务作为新的理念和原来的分布式系统,或者说SOA(面向服务架构)是什么区别呢? 我们先看相同点: 需要Registry,实现动态的服务注册发现机制:需要考虑分布式下面的事务一致性,CAP原则下,两段式提交不能保证性能,事务补偿机制需要考虑:同步调用还是异步消息传递,如何保证消息可靠性?SOA由ESB来集成所有的消息:都需要统一的Gateway来汇

Spring核心——Bean的定义与控制

在前面两篇介绍Sring核心与设计模式的文章中,分别介绍了Ioc容器和Bean的依赖关系.如果阅读过前2文就会知道,Spring的整个运转机制就是围绕着IoC容器以及Bean展开的.IoC就是一个篮子,所有的Bean都向里面扔.除了提供篮子功能创建并存放Bean之外,IoC还要负责管理Bean与Bean之间的关系--依赖注入.之前也提到Bean是Spring核心容器的最小工作单元,Spring一些更高级的功能(例如切面.代理)都是在Bean的基础上实现. 除了管理Bean与Bean之间的关系,I