• 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的帮助文档也给我们提供了相当全面且详细的说明。

    欢迎提出意见或建议!!!
  • 相关阅读:
    C#托盘图标
    线程相关整理
    Quartz.NET 快速入门
    (转)IE内存泄露,iframe内存泄露造成的原因和解决方案
    美化console.log的文本(转载)
    mongoDB学习资料整理
    EF7学习资料整理
    Oracle常用
    Node.js学习资料整理
    【大型网站技术实践】初级篇:借助Nginx搭建反向代理服务器(转)
  • 原文地址:https://www.cnblogs.com/gaofei-1/p/7367598.html
Copyright © 2020-2023  润新知