摘录一些Spring文档的内容(一)

log4j.properties样板(用于配置控制台输出信息)

log4j.rootCategory=INFO, stdout

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{2}:%L - %m%n

log4j.category.org.springframework.beans.factory=DEBUG

Spring中如果要把Log4J和默认的JCL依赖( commons-logging )一起使用,你只需要 将Log4J放在类路径下并提供一个配置文件( log4j.properties 或者 log4j.xml 放在类路径的根目录下)

基于XML的配置元数据的基础结构(用于声明配置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.xsd">

    <bean id="..." class="...">
        <!-- 在这里写 bean 的配置和相关引用 -->
    </bean>

    <bean id="..." class="...">
        <!-- 在这里写 bean 的配置和相关引用 -->
    </bean>

    <!-- 更多bean的定义写在这里 -->

</beans>

例如:
service.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.xsd">

    <!-- services -->

    <bean id="petStore" class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl">
        <property name="accountDao" ref="accountDao"/>
        <property name="itemDao" ref="itemDao"/>
        <!-- 在这里写额外的bean的配置和相关引用 -->
    </bean>

    <!-- 更多Service层的bean定义写在这里 -->

</beans>

dao.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.xsd">

    <bean id="accountDao"
        class="org.springframework.samples.jpetstore.dao.jpa.JpaAccountDao">
        <!-- 在这里写额外的bean的配置和相关引用 -->
    </bean>

    <bean id="itemDao" class="org.springframework.samples.jpetstore.dao.jpa.JpaItemDao">
        <!-- 在这里写额外的bean的配置和相关引用 -->
    </bean>

    <!-- 更多数据访问层的bean定义写在这里 -->

</beans>

id属性是一个用来识别每一个独立bean定义的字符串。class属性定义了bean的类型,这个属性需要使用bean类的全限定名称。id属性的值可以被其他的bean对象引用
id和ref的关系表达出了这两个对象间的依赖关系

实例化Spring IoC容器很容易。将一个或多个位置路径提供给ApplicationContext的构造方法就可以让容器加载配制元数据,可以从多种外部资源进行获取,例如文件系统、Java的CLASSPATH等等。

使用应用上下文的构造方法从多个XML片段中加载bean的定义

<beans>
    <import resource="services.xml"/>
    <import resource="resources/messageSource.xml"/>
    <import resource="/resources/themeSource.xml"/>

    <bean id="bean1" class="..."/>
    <bean id="bean2" class="..."/>
</beans>

外部的bean定义从services.xml、messageSource.xml和themeSource.xml这三个文件中加载。些被引入文件的内容会被导入进来,包含顶层的<beans/>元素,它必须是一个符合Spring架构的有效的XML bean定义。

实例化容器

ApplicationContext context =
    new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});

使用容器

// 创建并配置beans
ApplicationContext context =
    new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});

// 取得配置的实例
PetStoreService service = context.getBean("petStore", PetStoreService.class);

// 使用实例
List<String> userList = service.getUsernameList();

ApplicationContext是智能的工厂接口,它能够维护注册不同beans和它们的依赖。通过使用 T getBean(String name, Class<T> requiredType) 方法,你可以取得这些beans的实例。(应用程序中,不需要调用getBean()等方式获取,Spring和web框架的集成后 会为web框架组件 提供各种依赖注入的特性,你只需要通过元数据(metadata)的方式(如:通过autowiring注解)声明一个具体的bean就可以了)。

Bean的概述

一个Spring IoC容器管理了一个或者多个 beans。这些beans通过你提供给容器的配置元数据进行创建,例如通过XML形式的<bean/>定义。
在容器内本身,这些bean定义表示为BeanDefinition对象。

bean的定义.png

bean的id和name不是必须的。如果没有明确的name或者id,容器会给bean生成一个唯一的名字。 但是,如果你想通过名称引用这个bean,通过使用ref元素或Service Locator 查找,你就必须提供一个名字。

Bean的别名定义(在配置文件的合适位置定义别名)

<alias name="fromName" alias="toName"/>

id属性指定一个唯一的名称外,为了提供多个名称,需要通过name属性加以指定,所有这个名称都指向同一个bean,在某些情况下提供别名非常有用,比如为了让应用每一个组件都能更容易的对公共组件进行引用。

Bean的实例化

Bean的定义实际上就是告诉Spring怎么样创建一个或多个对象。当需要用到bean的时候,容器查看Bean的定义以及相关配置元数据 创建对象。

容器使用Class属性(通过class属性来指定对象的类型)实例化Bean的两种方式:

  • 通常,容器通过反射的方式获取Class的构造方法来创建bean,就和在java代码中用new的方式创建一个对象相似。
  • 不太常见的情况下,容器调用静态工厂方法创建对象。

内部类名

例如,在com.example包下有个Foo类,这里类里面有个静态的内部类Bar,这种情况下bean定义的class属性应该…​

com.example.Foo$Bar

注意,使用$字符来分割外部类和内部类的名称。

Spring IoC 容器可以管理几乎所有你想让它管理的类,它不限于管理POJO。大多数Spring用户更喜欢使用POJO(一个默认无参的构造方法和setter,getter方法)。但在容器中使用非bean形式(non-bean style)的类也是可以的。比如遗留系统中的连接池,很显然它与JavaBean规范不符,但Spring也能管理它

依赖解决步骤

容器解决依赖问题通常有以下几个步骤:

  • 描述所有bean的ApplicationContext 创建并根据配置的元数据初始化。配置的元数据可以通过置顶的XML,Java代码或者注解。
  • 每个bean的依赖将以属性,构造器参数或者静态工厂方法的形式出现。当这些bean被创建时,这些依赖将会提供给该bean。
  • 每个属性或者构造器参数既可以是一个实际的值也可以是容器中的另一个引用。
  • 每个指定的属性或者构造器参数值必须能够被转换成特定的格式或构造参数所需的类型。默认情况下Spring会以String类型转换为各种内置类型,比如int,long, String, boolean等。

当Spring容器创建时容器会校验每个bean的配置。但是在bean被实际创建 前,bean的值并不会被设置。那些单例类型的bean和被设置为预安装(默认)的bean会在容器创建时与容器同时创建。Scopes是在Bean作用域中定义的。同时,另外的bean只会在被需要时创建。伴随着bean被实际创建,作为该bean的依赖和它的依赖的依赖(以此类推)会被创建和分配。注意 这些依赖之间的解决会显示迟一些

Bean的作用域

Spring 框架支持五种开箱即用的作用域,其中三种仅在基于 web 的 ApplicationContext 中使用。

Bean作用域.png
  • 单例作用域
    当你定义一个 bean 定义,并且它的作用域为单例的,Spring IoC 容器就会精确地(exactly)创建一个(one)对象实例。这个实例被存储在一个包含很多单例 bean 的缓存中。并且所有的后来的请求和引用(all subsequent requests and references)都会返回缓存的对象
单例作用域.png
  • 原型作用域
    bean使用原型作用域而不是单例作用域的话,会在每次请求该bean,也就是bean被注入至另一个bean、 或通过调用Spring容器的 getBean() 方法时,创建一个新的bean实例 。 通常,对于有状态的bean使用原型作用域,无状态的bean则使用单例作用域。
原型作用域.png

与其他作用域不同的是,Spring容器不会管理原型域bean的完整生命周期:Spring容器会初始化、 配置,亦或者组装原型域的bean对象,然后交给客户端,之后就再也不会管这个bean对象了。 因此,对于bean的生命周期方法来说,尽管所有作用域的 初始化方法 都会被调用, 但是原型域bean的 销毁方法 不会 被Spring容器调用。客户端代码要自己负责销毁原型域bean 以及和bean相关的资源(特别是开销大的资源)。如果想让Spring负责这些事(销毁bean、释放资源), 就得自定义bean的后处理器 bean post-processor ,它会持用原型域bean的引用。

从某种意义上说,对于原型域bean,Spring容器代替了Java 的 new 操作符。所有在 new 之后的生命周期管理任务, 都要由客户端自行处理。

  • 基本的web配置

了使用请求 request 、会话 session 和全局会话 global session 等作用域(web作用域), 在定义bean之前要做一些最基本的初始化配置。(如果使用单例和原型这类标准作用域,是 不需要 这些初始化配置的)。

具体如何组装这些初始化配置与你使用的特定的Servlet环境有关..

事实上,如果你使用Spring Web MVC ,在 DispatcherServlet 或 DispatcherPortlet 处理的请求内去访问这些作用域的bean, 那就不用做任何专门的配置:DispatcherServlet 和 DispatcherPortlet 已经帮你做了这些事情。

如果你使用的是 Servlet2.5 标准的web容器,而且请求不是由 Spring的 DispatcherServlet 处理 (例如使用了Struts或JSF),你就得注册 org.springframework.web.context.request.RequestContextListener 这一 ServletRequestListener 。 对于Servlet 3.0 以上的环境,可以通过 WebApplicationInitializer 接口以代码的方式去实现。 或者,对于比较老旧的web 容器,在 web.xml 配置文件中加入以下的声明:

<web-app>
    ...
    <listener>
        <listener-class>
            org.springframework.web.context.request.RequestContextListener
        </listener-class>
    </listener>
    ...
</web-app>
```
又或者,如果你在配置监听器时有问题,也可以使用 RequestContextFilter 。过滤器的映射与具体的web应用有关,所以你得自行修改映射的内容。
````xml
<web-app>
    ...
    <filter>
        <filter-name>requestContextFilter</filter-name>
        <filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>requestContextFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    ...
</web-app>

DispatcherServlet, RequestContextListener 和 RequestContextFilter 做的事情是一样的,都是把每个http请求对象绑定到处理线程 Thread 上, 那么,请求、会话和全局会话作用域bean就可以沿着调用链继续往下走了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容