Spring知识整理

Spring

1.Spring演进:

  1. Spring框架所倡导的基于POJO(Plain Old Java Object,简单Java对象)的轻量级开发理念,就是从实际出发,立足于最基础的POJO(就好像我们的地球)。为了能够让这些基础的POJO构建出健壮而强大的应用,Spring框架就好像那包裹地球的大气层一样,为构筑应用的POJO提供了各种服务,进而创造了一套适宜用POJO进行轻量级开发的环境。
  2. 整个Spring框架构建在Core核心模块之上,它是整个框架的基础。AOP模块提供了一个轻便但功能强大的
    AOP框架,让我们可以以AOP的形式增强各POJO的能力,进而补足OOP/OOSD之缺憾。
  3. Spring框架在Core核心模块和AOP模块的基础上,为我们提供了完备的数据访问和事务管理的抽象和集成服务。Spring框架中的事务管理抽象层是Spring AOP的最佳实践,它直接构建在Spring AOP的基础之上,为我们提供了编程式事务管理和声明式事务管理的完备支持。
  4. 为了简化各种Java EE服务(像JNDI、JMS以及JavaMail等)的使用,Spring框架为我们提供了针
    对这些Java EE服务的集成服务。
  5. 最后要提到的就是Web模块。在该模块中,Spring框架提供了一套自己的Web MVC框架,职责分
    明的角色划分让这套框架看起来十分地“醒目”。

不要只将Spring看作是一个IoC容器,也不要只将Spring与AOP挂钩Spring提供的远比这些东西要多得多。

Spring不仅仅是一个简化Java EE开发的轻量级框架,它更应该是一个简化任何Java应用的开发框架。

2.IOC

2.1. IOC概念:
  • Inversion of Control(控制反转),别名依赖注入(Dependency Injection)。IoC的理念就是,
    让别人为你服务!

<img src="figures/ioc01.png" style="zoom:80%" />

通常,被注入对象会直接依赖于被依赖对象。但是,在IoC的场景中,二者之间通过IoC Service
Provider来打交道,所有的被注入对象和依赖对象现在由IoC Service Provider统一管理。被注入对象需要
什么,直接跟IoC Service Provider招呼一声,后者就会把相应的被依赖对象注入到被注入对象中,从而
达到IoC Service Provider为被注入对象服务的目的。IoC Service Provider在这里就是通常的IoC容器所充
当的角色。

2.2. IOC依赖注入的方式:
  • 三种依赖注入的方式,即构造方法注入(constructor injection)、setter方法注入(setter injection)以及接口注入(interface injection)。
  • 构造方法注入:被注入对象可以通过在其构造方法中声明依赖对象的参数列表,让外部(通常是IoC容器)知道它需要哪些依赖对象。IoC 会检查被注入对象的构造方法,取得它所需要的依赖对象列表,进而为其注
    入相应的对象。同一个对象是不可能被构造两次的,因此,被注入对象的构造乃至其整个生命周期,
    应该是由IoC 容器来管理的。
  • setter方法注入:对于JavaBean对象来说,通常会通过 setXXX() 和 getXXX() 方法来访问对应属性。这些 setXXX() 方法统称为setter方法, getXXX() 当然就称为getter方法。通过setter方法,可以更改相应的对象属性,通过getter方法,可以获得相应属性的状态。setter方法注入虽不像构造方法注入那样,让对象构造完成后即可使用,但相对来说更宽松一些,可以在对象构造完成后再注入。

3. IoC Service Provider之IOC容器:

  • 职责:业务对象的构建管理和业务对象间的依赖绑定
  • 如何管理对象间的依赖关系:IoC Service Provider同样需要知道自己所管理和掌握的被注入
    对象和依赖对象之间的对应关系。
  • 如何记录记录诸多对象之间的对应关系:1. 配置文件 2. 注解(属性,构造器)

这里写图片描述

4. IOC容器之BeanFactory:

4.1. BeanFactory和ApplicationContext的区别:
  • ​ Beanfactory

基础类型IoC容器,提供完整的IoC服务支持。如果没有特殊指定,默认采用延 迟初始化策略(lazy-load)。只有当客户端对象需要访问容器中的某个受管对象的时候,才对 该受管对象进行初始化以及依赖注入操作。所以,相对来说,容器启动初期速度较快,所需 要的资源有限。对于资源有限,并且功能要求不是很严格的场景, BeanFactory 是比较合适的IoC容器选择。

  • ApplicationContext:

    在 BeanFactory 的基础上构建,是相对比较高级的容器实现, ApplicationContext 所管理的对象,在该类型容器启动之后,默认全部初始化并绑定完成。在那些系统资源充足,并且要求更多功能的场景中, ApplicationContext 类型的容器是比较合适的选择。

这里写图片描述

4.2. BeanFactory 的对象注册与依赖绑定方式:
  • BeanFactory中的方法:

这里写图片描述

​ BeanFactory 接口只定义如何访问容器内管理的Bean的方法,各个 BeanFactory 的具体实现类负责具体Bean的注册以及管理工作。BeanDefinitionRegistry 接口定义抽象了Bean的注册逻辑。如下:

这里写图片描述

  1. BeanFactory 相当于图书馆、BeanDefinition相当于图书,BeanDefinitionRegistry相当于书架。
  2. BeanDefinition 的实例(instance)与对象相对应,该BeanDefinition 的实例负责保存对象的所有必要信息,当客户端向 BeanFactory 请求相应对象的时候, BeanFactory 会通过这些信息为客户端返回一个完备可用的对象实例。
4.2.1 外部配置文件方式

支持Properties文件格式和XML文件格式。

通常情况下,需要根据不同的外部配置文件格式,给出相应的 BeanDefinitionReader 实现类,由 BeanDefinitionReader 的相应实现类负责将相应的配置文件内容读取并映射到 BeanDefinition ,然后将映射后的 BeanDefinition 注册到一个 BeanDefinitionRegistry ,之后, BeanDefinitionRegistry 即完成Bean的注册和加载。

BeanDefinitionRegistry beanRegistry = <某个BeanDefinitionRegistry 实现类,通常为
DefaultListableBeanFactory>;
BeanDefinitionReader beanDefinitionReader = new BeanDefinitionReaderImpl(beanRegistry);
beanDefinitionReader.loadBeanDefinitions("配置文件路径");
// 现在我们就取得了一个可用的BeanDefinitionRegistry实例
  • Properties配置格式的加载

  • XML配置文件的加载: 首先给出相应的BeanDefinitionReader 实现类 ,由 BeanDefinitionReader 的相应实

public static void main(String[] args)
{
    DefaultListableBeanFactory beanRegistry = new DefaultListableBeanFactory();
    BeanFactory container = (BeanFactory)bindViaXMLFile(beanRegistry);
    FXNewsProvider newsProvider = (FXNewsProvider)container.getBean("djNewsProvider");
    newsProvider.getAndPersistNews();
}
public static BeanFactory bindViaXMLFile(BeanDefinitionRegistry registry)
{
    XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(registry); 
    reader.loadBeanDefinitions("classpath:../news-config.xml");
    return (BeanFactory)registry;
    // 或者直接
    //return new XmlBeanFactory(new ClassPathResource("../news-config.xml"));
}
4.2.2 注解方式

@Autowired 是这里的主角,它的存在将告知Spring容器需要为当前对象注入哪些依赖对象。而
@Component 则是配合Spring 2.5中新的classpath-scanning功能使用的。

  • 使用时需要加入“触发器”:

    <context:component-scan base-package="cn.spring21.project.base.package"/>

< context:component-scan/> 会到指定的包(package)下面扫描标注有 @Component 的类,如果
找到,则将它们添加到容器进行管理,并根据它们所标注的 @Autowired 为这些类注入符合条件的依
赖对象。

4.3 BeanFactory 中 XML的使用
4.3.1 < beans> 和 < bean>
  • < beans>是XML配置文件中最顶层的文件, < beans>可以设置如下几个属性:

    1. default-lazy-init 。默认值为 false,是否对所有的 < bean> 进行延迟初始化
    2. default-autowire。 默认取值为 no ,可以 byName 、 byType 、 constructor 以及 autodetect
    3. default-dependency-check 。默认值为 none ,即不做依赖检查。
    4. default-init-method 。
    5. default-destroy-method 。
  • <bean id="djNewsListener" class="..impl.DowJonesNewsListener"
    name="/news/djNewsListener,dowJonesNewsListener">
    </bean>
    1. id: 唯一标志
    2. name: 别名,可以使用 id 不能使用的一些字符
    3. class 属性
  • < bean>中构造方法注入

    1. 两种写法
    <bean id="djNewsProvider" class="..FXNewsProvider">
    <constructor-arg>
        <ref bean="djNewsListener"/>
    </constructor-arg>
      <constructor-arg ref="djNewsPersister"/>
    </bean>
    1. type属性

    如果是想调用的是传入int类型的构造方法,怎么做呢?

    <bean id="mockBO" class="..MockBusinessObject">
    <constructor-arg type="int">
        <value>111111</value>
    </constructor-arg>
    < /bean>
    1. index属性

    当构造方法同时传入了多个类型相同的参数时,可以这样:

    <bean id="mockBO" class="..MockBusinessObject">
    <constructor-arg value="11111"/>
    <constructor-arg value="22222"/>
    </bean>

    或者

    <bean id="mockBO" class="..MockBusinessObject">
    <constructor-arg index="1" value="11111"/>
    <constructor-arg index="0" value="22222"/>
    </bean>

    此时,第一个属性的值是22222, 第二个属性的值是11111.

  • < bean>中setter方法注入

<bean id="djNewsProvider" class="..FXNewsProvider">
    <property name="newsListener">
        <ref bean="djNewsListener"/>
    </property>
    <property name="newPersistener" ref="djNewsPersister"/>
</bean>

property 属性:name:指定该 将会注入的对象所对应的实例变量名称

​ ref/value:具体的依赖对象引用或者值

setter注入和构造器注入可以同时用

  • < property>和< constructor-arg>中可用的配置项

可配置:bean、ref、idref、value、null、list、set、map、props

value: 注入简单的数据类型

ref:指定引用对象的beanName

idref:为当前对象注入所依赖的对象的名称

内部bean: 只有当前一个对象引用时使用

  • depends-on

没有通过类似 < ref> 的元素明确指定对象A依赖于对象B的话,如何让容器在实例化对象A之前首先实例化对象B?

使用depengs-on:

<bean id="classAInstance" class="...ClassA" depends-on="configSetup"/>
<bean id="configSetup" class="SystemConfigurationSetup"/>
  • autowire

Spring根据bean定义的某些特点将相互依赖的某些bean直接自动绑定的功能

5中模式: no 、 byName 、 byType 、 constructor 和 autodetect

示例: byName:

public class Foo
{
private Bar emphasisAttribute;
    ...
    // 相应的setter方法定义
}
public class Bar
{
    ...
}
<bean id="fooBean" class="...Foo" autowire="byName">
</bean>
<bean id="emphasisAttribute" class="...Bar">
</bean>

第二个bean定义的 id 为 emphasisAttribute ,与 Foo 类中的实例变量名称相同。

  • dependency-check 依赖检查

  • lazy-init 延迟初始化( lazy-init ),主要针对ApplicationContext 容器, 设置某一个bean延迟初始化,但是还是得看有没有bean依赖它。

    我们还可以通过beans设置同意得延迟初始化:< beans default-lazy-init=”true” >


4.3.2 bean定义中的继承 (还没看)
4.3.3 bean的scope(single 和 prototype的作用范围)

scope用来声明容器中的对象所应该处的限定场景或者说该对象的存活时间

  • 使用:
DTD:
<bean id="mockObject1" class="...MockBusinessObject" singleton="false"/>
XSD:
<bean id="mockObject2" class="...MockBusinessObject" scope="prototype"/>
  • single

单例,Spring的IoC容器中只存在一个实例,所有对该对象的引用将共享这个实例。

该实例从容器启动,并因为第一次被请求而初始化之后,将一直存活到容器退出,也就是说,它与IoC容器“几乎”拥有相同的“寿命”。

  • protorype

原型, 容器在接到该类型对象的请求的时候,会每次都重新生成一个新的对象实例给请求方。

但是,只要对象实例返回给请求方时, 容器就不再拥有当前返回对象的引用,请求方需要自己负责当前返回对象的后继生命周期的管理工作,包括该对象的销毁。

对于那些请求方不能共享使用的对象类型,应该将其bean定义的scope设置为prototype,通常,声明
为prototype的scope的bean定义类型,都是一些有状态的,比如保存每个顾客信息的对象。

  • 其他用在网络中的,request、session和global session
4.3.4. 工厂方法和FactoryBean:
  • 针对使用工厂方法模式实例化对象的方式,Spring的IoC容器同样提供了对应的集成支持。
  • FactoryBean 是Spring容器提供的一种可以扩展容器对象实例化逻辑的接口。,它本身与其他注 册到容器的对象一样,只是一个Bean而已,只不过,这种类型的Bean本身就是生产对象的工厂 (Factory)。
  • 当某些对象的实例化过程过于烦琐,通过XML配置过于复杂,使我们宁愿使用Java代码来完成这 个实例化过程的时候,或者,某些第三方库不能直接注册到Spring容器的时候,就可以实现 org.spring.framework.beans.factory.FactoryBean 接口,给出自己的对象实例化逻辑代码。
使用FactoryBean:
package org.springframework.beans.factory;

public interface FactoryBean<T> {
    T getObject() throws Exception;

    Class<?> getObjectType();

    boolean isSingleton();
}
  • getObject() 方法会返回该 FactoryBean “生产”的对象实例,我们需要实现该方法以给出自己
    的对象实例化逻辑;

使用实例:

  1. 继承FactoryBean
public class NextDayDateFactoryBean implements FactoryBean {
 public Object getObject() throws Exception {
    return new DateTime().plusDays(1);
 }
 public Class getObjectType() {
    return DateTime.class;
 }
 public boolean isSingleton() {
    return false;
 }
}
  1. XML定义
<bean id="nextDayDateDisplayer" class="...NextDayDateDisplayer">
    <property name="dateOfNextDay">
        <ref bean="nextDayDate"/>
    </property>
</bean>
<bean id="nextDayDate" class="...NextDayDateFactoryBean">
</bean>
  1. 可能上面看不到FactoryBean 的魔力到底在哪。 NextDayDateDisplayer 的定义如下:
public class NextDayDateDisplayer
{
    private DateTime dateOfNextDay;
    // 相应的setter方法
    // ...
}

NextDayDateDisplayer 所声明的依赖 dateOfNextDay 的类型为 DateTime ,而不是NextDayDateFactoryBean 。

  1. 如果一定要取得 FactoryBean 本身的话,可以通过在bean定义的 id 之前加前缀 & 来达到目的。
Object nextDayDate = container.getBean("nextDayDate");
assertTrue(nextDayDate instanceof DateTime);

Object factoryBean = container.getBean("&nextDayDate");
assertTrue(factoryBean instanceof FactoryBean);
assertTrue(factoryBean instanceof NextDayDateFactoryBean);
4.3.5. 方法注入和方法替换(偷梁换柱)
  • 方法注入:方法申明符合

    <public|protected> [abstract] <return-type> theMethodName(no-arguments);
    <bean id="newsBean" class="..domain.FXNewsBean" singleton="false">
    </bean>
    <bean id="mockPersister" class="..impl.MockNewsPersister">
    <lookup-method name="getNewsBean" bean="newsBean"/>
    </bean>
  • 使用 BeanFactoryAware 接口

    让当前类中拥有一个BeanFactory的引用。

4.3. 容器背后的秘密
  • Spring的IoC容器所起的作用:它会以某种方式加载ConfigurationMetadata(通常也就是XML格式的配置信息),然后根据这些信息绑定整个系统的对象,最终组装成一个可用的基于轻量级容器的应用系统。 可以划分为两个阶段:容器启动阶段Bean实例化阶段。 Spring充分运用了这两个实现阶段的不同特点,在每个阶段都加入了相应的容器扩展点,以便我们可以根据具体场景的需要加入自定义的扩展逻辑。

5. IOC容器之ApplicationContext:

ApplicationContext 在 BeanFactory 的基础上构建,是相对比较高 级的容器实现,除了拥有 BeanFactory 的所有支持, ApplicationContext 还提供了其他高级特性,比如事件发布、国际化信息支持等,这些会在后面详述。ApplicationContext 所管理 的对象,在该类型容器启动之后,默认全部初始化并绑定完成。ApplicationContext在启动时就完成所有初始化,容器启动时间较之 BeanFactory 也会长一些。

6.AOP

7.事务

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值