Spring 介绍

2018-06-04  本文已影响16人  王某某的笔记

从这个地方随手翻译过来的
https://www.tutorialspoint.com/spring/index.htm
王某某

概述

Spring是企业Java最流行的应用程序开发框架。全球数以百万计的开发人员使用Spring Framework创建高性能,易于测试和可重用的代码。

Spring框架是一个开源的Java平台。它最初由Rod Johnson编写,并于2003年6月首次在Apache 2.0许可下发布。

Spring框架的核心功能可以用于开发任何Java应用程序,但是在Java EE平台之上还可以扩展构建Web应用程序。Spring框架的目标是通过启用基于POJO的编程模型来使J2EE开发更易于使用,并促进良好的编程实践。

依赖注入(DI)

Spring最认常用技术是控制反转的依赖注入(DI)。该控制反转(IOC)是一个笼统的概念,它可以在许多不同的方式来表达。依赖注入仅仅是控制反转的一个具体例子。

面向切面编程(AOP)

Spring的关键组件之一是面向切面编程(AOP)框架。跨越应用程序多个点的功能称为横切关注点,这些横切关注点在概念上与应用程序的业务逻辑分离。有各种常见的很好的例子,包括日志记录,声明式事务,安全性,缓存等等。


框架

Spring框架提供了大约20个模块,可以根据应用需求使用。

核心容器

核心容器由Core,Beans,Context和Expression Language模块组成

数据访问/集成

数据访问/集成层由JDBC,ORM,OXM,JMS和事务模块组成

WEB

Web层由Web,Web-MVC,Web-Socket和Web-Portlet模块组成

杂项

重要模块像AOP,Aspects(切面),仪表,消息和测试模块等
...
...

Bean定义

构成应用程序主干和由Spring IoC容器管理的对象称为bean。bean是由Spring IoC容器实例化、组装和管理的对象。这些bean是用你提供给容器的配置元数据创建的。例如,XML <bean/>定义的形式

配置一个bean容器需要知道如下信息:

属性 说明
class 该属性是强制性的,指定了用于创建bean的类。
name 该属性唯一的指定了bean标识符。在基于XML的配置元数据中,使用id (and/or)name属性来指定bean标识符。
scope 指定了从特定的bean定义创建的对象的范围
constructor-arg 构造参数,用于注入依赖关系
properties 属性,用于注入依赖关系
autowiring mode 自动装配模式,用于注入依赖关系
lazy-initialization mode 延时加载,告诉IoC容器在第一次请求时创建一个bean实例,而不是在启动时
initialization method 初始化方法,在bean的所有必要属性设置之后立即调用的回调方面
destruction method 销毁方法,在bean的容器被销毁时要调用的回调函数

Spring 配置

配置Spring一般包括3中方式

基于XML的配置文件示例:

<?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>

Bean的范围

定义一个<bean>时,你可以选择为该bean声明一个范围。例如,为了强制Spring在每次需要时产生一个新的bean实例,你应该声明bean的scope属性是prototype。同样,如果你希望Spring在每次需要时都返回相同的bean实例,你应该声明bean的scope属性为singleton

Spring框架支持以下五个范围,其中三个仅在您使用Web感知的ApplicationContext时才可用。

范围 说明
singleton 单实例,每次都使用同一个bean(默认值),对象创建好之后会被缓存,
prototype 多实例,每次都返回新的实例
request 在一次HTTP请求中使用相同实例。
只有在Web感知的Spring ApplicationContext的上下文中才有效。
session 在一个HTTP会话中使用相同实例。
只有在Web感知的Spring ApplicationContext的上下文中才有效。
global-session 在一个全局HTTP会话中使用相同实例。
只有在Web感知的Spring ApplicationContext的上下文中才有效。

Bean的生命周期

初始化回调

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"/>

public class ExampleBean {
   public void init() {
      // do some initialization work
   }
}

销毁回调

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

对于基于XML的配置元数据,可以使用destroy-method属性来指定具有void无参数签名的方法的名称。例如:

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

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

默认初始化和销毁方法

如果你的bean有太多具有相同名称的初始化和/或销毁方法,则不需要在每个单独的bean上声明init-method和destroy-method。这种情况可以使用<beans>元素上的default-init-method和default-destroy-method属性来配置,如下所示:

<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>

Bean Post Processors

BeanPostProcessor接口定义了回调方法,你可以实现这些方法来提供您自己的实例化逻辑、依赖解析逻辑等。还可以在Spring容器完成实例化、配置和初始化bean之后,通过插入一个或多个BeanPostProcessor实现来实现一些自定义逻辑。
可以配置多个BeanPostProcessor接口,并且您可以通过设置order属性来控制这些BeanPostProcessor接口执行的顺序。

ApplicationContext自动检测由BeanPostProcessor接口实现定义的任何bean,并将这些bean注册为postprocessor,然后容器在创建bean时相应地调用这些bean。

HelloWorld.java文件的内容:

package com.tutorialspoint;

public class HelloWorld {
   private String message;

   public void setMessage(String message){
      this.message  = message;
   }
   public void getMessage(){
      System.out.println("Your Message : " + message);
   }
   public void init(){
      System.out.println("Bean is going through init.");
   }
   public void destroy(){
      System.out.println("Bean will destroy now.");
   }
}

InitHelloWorld.java文件

package com.tutorialspoint;

import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.BeansException;

public class InitHelloWorld implements BeanPostProcessor {
   public Object postProcessBeforeInitialization(Object bean, String beanName) 
      throws BeansException {
      
      System.out.println("BeforeInitialization : " + beanName);
      return bean;  // you can return any other object as well
   }
   public Object postProcessAfterInitialization(Object bean, String beanName) 
      throws BeansException {
      
      System.out.println("AfterInitialization : " + beanName);
      return bean;  // you can return any other object as well
   }
}

Beans.xml 文件

<?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">

   <bean id = "helloWorld" class = "com.tutorialspoint.HelloWorld"
      init-method = "init" destroy-method = "destroy">
      <property name = "message" value = "Hello World!"/>
   </bean>

   <bean class = "com.tutorialspoint.InitHelloWorld" />

</beans>

MainApp.java文件

package com.tutorialspoint;

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

public class MainApp {
   public static void main(String[] args) {
      AbstractApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");

      HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
      obj.getMessage();
      context.registerShutdownHook();
   }
}

执行结果:

BeforeInitialization : helloWorld
Bean is going through init.
AfterInitialization : helloWorld
Your Message : Hello World!
Bean will destroy now.

Bean定义继承

bean定义可以包含许多配置信息,包括构造函数参数、属性值和容器特定的信息,如初始化方法、静态工厂方法名称等。

子bean定义从父定义继承配置数据。子定义可以覆盖一些值,或者根据需要添加其他值。
Spring Bean定义继承与Java类继承没有关系,但是继承概念是相同的。可以将父bean定义定义定义为模板,其他子bean可以从父bean继承所需的配置。

当使用基于xml的配置元数据时,您通过使用父属性指定子bean定义,指定父bean作为该属性的值。

<?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">

   <bean id = "helloWorld" class = "com.tutorialspoint.HelloWorld">
      <property name = "message1" value = "Hello World!"/>
      <property name = "message2" value = "Hello Second World!"/>
   </bean>

   <bean id =" helloIndia" class = "com.tutorialspoint.HelloIndia" parent = "helloWorld">
      <property name = "message1" value = "Hello India!"/>
      <property name = "message3" value = "Namaste India!"/>
   </bean>
</beans>

定义模板

定义Bean定义模板时,不应指定类属性

<?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">

   <bean id = "beanTeamplate" abstract = "true">
      <property name = "message1" value = "Hello World!"/>
      <property name = "message2" value = "Hello Second World!"/>
      <property name = "message3" value = "Namaste India!"/>
   </bean>

   <bean id = "helloIndia" class = "com.tutorialspoint.HelloIndia" parent = "beanTeamplate">
      <property name = "message1" value = "Hello India!"/>
      <property name = "message3" value = "Namaste India!"/>
   </bean>
   
</beans>

父bean不能自行实例化,因为它是不完整的,并且它也明确标记为抽象。当定义像这样抽象时,它只能用作纯模板bean定义,作为子定义的父定义。

依赖注入

依赖注入主要包括基于构造函数的依赖注入和基于Setter的依赖注入

基于setter的注入但使用内部bean的配置

<?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">

   <!-- Definition for textEditor bean using inner bean -->
   <bean id = "textEditor" class = "com.tutorialspoint.TextEditor">
      <property name = "spellChecker">
         <bean id = "spellChecker" class = "com.tutorialspoint.SpellChecker"/>
      </property>
   </bean>

</beans>

注入集合

包括list、set、map、props

<?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">

   <!-- Definition for javaCollection -->
   <bean id = "javaCollection" class = "com.tutorialspoint.JavaCollection">
      
      <!-- results in a setAddressList(java.util.List) call -->
      <property name = "addressList">
         <list>
            <value>INDIA</value>
            <value>Pakistan</value>
            <value>USA</value>
            <value>USA</value>
         </list>
      </property>

      <!-- results in a setAddressSet(java.util.Set) call -->
      <property name = "addressSet">
         <set>
            <value>INDIA</value>
            <value>Pakistan</value>
            <value>USA</value>
            <value>USA</value>
         </set>
      </property>

      <!-- results in a setAddressMap(java.util.Map) call -->
      <property name = "addressMap">
         <map>
            <entry key = "1" value = "INDIA"/>
            <entry key = "2" value = "Pakistan"/>
            <entry key = "3" value = "USA"/>
            <entry key = "4" value = "USA"/>
         </map>
      </property>
      
      <!-- results in a setAddressProp(java.util.Properties) call -->
      <property name = "addressProp">
         <props>
            <prop key = "one">INDIA</prop>
            <prop key = "one">INDIA</prop>
            <prop key = "two">Pakistan</prop>
            <prop key = "three">USA</prop>
            <prop key = "four">USA</prop>
         </props>
      </property>
   </bean>

</beans>

将bean引用注入为集合元素中,使引用和值混合在一起

<?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">

   <!-- Bean Definition to handle references and values -->
   <bean id = "..." class = "...">

      <!-- Passing bean reference  for java.util.List -->
      <property name = "addressList">
         <list>
            <ref bean = "address1"/>
            <ref bean = "address2"/>
            <value>Pakistan</value>
         </list>
      </property>
      
      <!-- Passing bean reference  for java.util.Set -->
      <property name = "addressSet">
         <set>
            <ref bean = "address1"/>
            <ref bean = "address2"/>
            <value>Pakistan</value>
         </set>
      </property>
      
      <!-- Passing bean reference  for java.util.Map -->
      <property name = "addressMap">
         <map>
            <entry key = "one" value = "INDIA"/>
            <entry key = "two" value-ref = "address1"/>
            <entry key = "three" value-ref = "address2"/>
         </map>
      </property>
   </bean>

</beans>

要使用上面的bean定义,你需要定义你的setter方法,以便它们也能够处理引用。

注入空和空字符串值

空字符串作为值:

<bean id = "..." class = "exampleBean">
   <property name = "email" value = ""/>
</bean>

传递一个NULL值

<bean id = "..." class = "exampleBean">
   <property name = "email"><null/></property>
</bean>

等同于:exampleBean.setEmail(null)

上一篇下一篇

猜你喜欢

热点阅读