Spring入门学习笔记(1)

该篇随笔,主要用于记录Spring Framework 基础知识。由于笔者是初学者,见识与能力有限,难免出现错误,如果发现错误,望不吝赐教。

Spring好处

以下列出了使用Spring Framework的一些巨大好处

  • Spring使开发人员能够使用POJO开发企业级应用程序。仅使用POJO的好处是您不需要EJB容器产品(如应用程序服务器),但您可以选择仅使用强大的servlet容器(如Tomcat)或某些商业产品。

  • Spring采用模块化方式组织。即使包和类的数量很大,你也只需要担心你需要的那些而忽略其余的。

  • Spring并没有重新发明轮子,而是真正利用了一些现有技术,如几个ORM框架,日志框架,JEE,Quartz和JDK计时器以及其他视图技术。

  • 测试用Spring编写的应用程序很简单,因为依赖于环境的代码被移动到这个框架中。此外,通过使用JavaBeanstyle POJO,使用依赖注入来注入测试数据变得更加容易。

  • Spring的Web框架是一个设计良好的Web MVC框架,它提供了一个很好的替代Web框架,如Struts或其他过度设计或不太流行的Web框架。

  • Spring提供了一个方便的API,用于将特定于技术的异常(例如,JDBC,Hibernate或JDO抛出)转换为一致的,未经检查的异常。

  • 轻量级IoC容器往往是轻量级的,尤其是与EJB容器相比时。这有利于在具有有限内存和CPU资源的计算机上开发和部署应用程序。

  • Spring提供了一致的事务管理接口,可以缩小到本地事务(例如,使用单个数据库)并扩展到全局事务(例如,使用JTA)。

依赖注入

  • Inversion of Control
  • 编写java程序,尽可能独立于其他java类,增加重用这些类的可能性
  • 含义:A依赖于B类,意味着,B类将由IoC注入A类

面向面编程(AOP)

  • 关键组件
  • 跨领域问题:日志记录,声明式事务,安全性,缓存等
  • AOP中,模块化单元是面
  • AOP可帮助您将交叉问题与它们所影响的对象分离
  • 允许定义方法拦截器和切入点,以便解耦。

Spring Framework

Core Container

  • Beans
    • Core,提供了框架的基本部分,包括IOC和依赖注入特征
    • Bean提供了BeanFactory,复杂的实现工厂模式
    • Context由core和bean提供,它是访问任何定义和配置的对象的媒介。ApplicationContext接口是上下文模块的焦点。
    • SpEL模块提供了一种强大的表达式语言,用于在运行时查询和操作对象图。

      Data Access/Integration

  • JDBC
  • ORM 模块为流行的对象关系映射api提供集成层,包括JPA、JDO、Hibernate和iBatis
  • OXM 模块提供了一个抽象层,支持JAXB、Castor、XMLBeans、JiBX和XStream的对象/XML映射实现。
  • JMS 包含用于生成和消费消息的特性。
  • Transaction 模块为实现特殊接口的类和所有pojo支持编程和声明式事务管理

Web

  • Web Web模块提供了基本的面向Web的集成特性,例如多部分文件上传功能,以及使用servlet侦听器和面向Web的应用程序上下文初始化IoC容器。
  • Web-MVC 模块包含Spring用于web应用程序的模型-视图-控制器(MVC)实现。
  • Web-Socket 模块在web应用程序中支持基于websocket的客户机和服务器之间的双向通信。
  • Web-Portlet 模块提供了在portlet环境中使用的MVC实现,并反映了web servlet模块的功能。

Miscellaneous

  • AOP模块提供了面向方面的编程实现,允许您将方法拦截器和切入点定义为实现应该分离的功能的干净解耦代码。
  • Aspects模块提供了与AspectJ的集成,这又是一个强大而成熟的AOP框架。
  • Instrumentation 模块提供了类插装支持和类装入器实现,用于某些应用服务器。
  • Messaging模块支持STOMP作为应用程序中使用的WebSocket子协议。它还支持一个注释编程模型,用于路由和处理来自WebSocket客户端的STOMP消息。
  • Test模块支持使用JUnit或TestNG框架测试Spring组件

编写第一个程序

  1. 使用IDEA创建Spring项目
  2. 创建HelloWorld文件
package top.ninwoo.learn;

public class HelloWorld {
    private String message;

    public void getMessage() {
        System.out.println("Your message " + message);
    }

    public void setMessage(String message) {
        this.message = message;
    }


}
  1. 创建Main函数
public class MainApp {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
        HelloWorld obj = (HelloWorld) context.getBean("helloworld");
        obj.getMessage();
    }
}

使用ClassPathXmlApplicationContext读取bean配置文件

  1. 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="helloworld" class="top.ninwoo.learn.HelloWorld">
        <property name="message" value="Hello World!"/>
    </bean>
</beans>

property 传入了HelloWorld的参数

IoC容器

  • Spring Framework的核心
  • 容器船舰对象,并连接彼此,并管理其生命周期
  • DI来管理组成应用程序的组件
  • 对象称为Spring Beans

Spring IoC容器利用Java POJO类和配置元数据来生成完全配置和可执行的系统或应用程序,配置元数据可以由:

  • XML
  • Java注释或Java代码表示

容器类型:

  • Spring BeanFactory: 最简单容器,目的向后兼容与Spring集成的大量第三方框架
  • Spring ApplicationContext: 添加了更多企业特有的功能,比如能够解析来自属性文件的文本消息,
    以及能够向感兴趣的事件侦听器发布应用程序事件。

ApplicationContext包含全部的BeanFactory,BeanFactory在小型化设备上仍可以用。

Spring Bean

构成应用程序主干并由Spring IoC容器管理的对象称为bean.

Bean的定义:

  • 如何创建Bean
  • Bean的生命周期细节
  • Bean的依赖关系

参数:

  1. class :必须,指定创建的Bean类
  2. name : 唯一指定Bean标识符,XML中可以使用id/name来指定
  3. scope : 作用域
  4. construtor-arg : 用于注入依赖项
  5. properties : 用于注入依赖项
  6. autowiring mode : 用于注入依赖项
  7. lazy-initialization mode : 延迟初始化的bean告诉IoC容器在第一次请求时创建bean实例,而不是在启动时创建
  8. initialization method : 在容器设置了bean之后所有必要属性之后调用的回调。它将在bean生命周期章节中讨论
  9. destruction method : 当Bean容器被销毁时使用的回调。

Spring配置元数据

方法:

  • XML
  • 注解
  • Java的配置
<?xml version = "1.0" encoding = "UTF-8"?>

<beans xmlns = "http://www.springframework.org/schema/beans"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <!-- A simple bean definition -->
   <bean id = "..." class = "...">
      <!-- collaborators and configuration for this bean go here -->
   </bean>

   <!-- A bean definition with lazy init set on -->
   <bean id = "..." class = "..." lazy-init = "true">
      <!-- collaborators and configuration for this bean go here -->
   </bean>

   <!-- A bean definition with initialization method -->
   <bean id = "..." class = "..." init-method = "...">
      <!-- collaborators and configuration for this bean go here -->
   </bean>

   <!-- A bean definition with destruction method -->
   <bean id = "..." class = "..." destroy-method = "...">
      <!-- collaborators and configuration for this bean go here -->
   </bean>

   <!-- more bean definitions go here -->
   
</beans>

Spring - Bean Scopes

当定义一个

Spring Framework 支持以下5种作用域,如果使用的是web-aware Application只有三种可用。

  • singleton : 将bean定义范围限定为每个Spring IoC容器的单个实例(默认)
  • prototype : 将bean定义范围限定为具有任意数量的对象实例
  • request : 将bean定义范围限定为HTTP请求。仅在Web感知Spring ApplicationContext的上下文中有效
  • session : 将bean定义范围限定为HTTP会话。仅在Web感知Spring ApplicationContext的上下文中有效。
  • global-session : 将bean定义范围限定为全局HTTP会话。仅在Web感知Spring ApplicationContext的上下文中有效。

singleton

只创建该Bean定义的对象的一个实例。

<!-- A bean definition with singleton scope -->
<bean id = "..." class = "..." scope = "singleton">
   <!-- collaborators and configuration for this bean go here -->
</bean>

配置完成之后,如下的代码,有以下的效果。

      ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
      HelloWorld objA = (HelloWorld) context.getBean("helloWorld");

      objA.setMessage("I'm object A");
      objA.getMessage();

      HelloWorld objB = (HelloWorld) context.getBean("helloWorld");
      objB.getMessage();

该程序打印:

I'm object A
I'm object A

这证明,实际只创建了一个bean对象,虽然调用了两次getBean,但返回的都是同一个对象。

prototype

每次调用bean,都会创建一个新的方法。

将上述的bean设置为prototype,执行同样的代码将会出现不同的效果。

该程序打印:

I'm object A
null

Spring-Bean Life Cycle

主要指的是,当bean被实例化时,可能需要执行一些初始化以使其进入可用状态。类似地,当不再需要bean并从容器中移除bean时,可能需要进行一些清理。

中间也存在一些活动,本章重点讨论以下两个声明周期回调方法。

  • initmethod
  • destroy-method

初始化回调

org.springframework.beans.factory.InitializingBean已经为我们提供了开发接口。

void afterPropertiesSet() throws Exception;

这样我们就可以通过实现上面的接口实现初始化工作

public class ExampleBean implements InitializingBean {
   public void afterPropertiesSet() {
      // do some initialization work
   }
}

另外,对于XML的配置元数据,可以通过init-method指定具有void无参数的方法

<bean id = "exampleBean" class = "examples.ExampleBean" init-method = "init"/>

销毁回调

org.springframework.beans.factory.DisposableBean也已经提供好了接口

void destroy() throws Exception;

这样,我们可以通过实现该接口实现销毁的工作

public class ExampleBean implements DisposableBean {
   public void destroy() {
      // do some destruction work
   }
}

注意:如果想要使该函数起作用,需要注册registerShutdownHook()方法。

同样,基于XML配置元数据,可以使用destroy-method指定具有void的无参方法

<bean id = "exampleBean" class = "examples.ExampleBean" destroy-method = "destroy"/>

建议还是使用XML的方式,更加灵活。

默认的初始化和销毁方法

如果很多bean都需要同名的初始化和销毁方法,可以在

<beans xmlns = "http://www.springframework.org/schema/beans"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
   default-init-method = "init" 
   default-destroy-method = "destroy">

   <bean id = "..." class = "...">
      <!-- collaborators and configuration for this bean go here -->
   </bean>
   
</beans>