Spring注意事项(各部分理解)

时间:2024-04-21 21:05:04

(1),每一个bean属性,就是一个普通的java类。
类有属性,有方法,如何交给容器管理。(注解的方式,xml方式配置)
(2),通过Bean来实例化对象的方式
1.通过构造器(一般是无参的默认构造器)
<bean id="exampleBean" class="examples.ExampleBean"/>
<bean name="anotherExample" class="examples.ExampleBeanTwo"/>
2.使用静态工厂方法实例化
下面的bean定义展示了如何通过工厂方法来创建bean实例。注意,此定义并 未指定返回对象的类型,仅指定该类包含的工厂方法。
在此例中, createInstance()必须是一个static方法。
<bean id="exampleBean"
class="examples.ExampleBean2"
factory-method="createInstance"/>
(3),使用实例工厂方法实例化
(4), 注入依赖
依赖注入(DI)背后的基本原理是对象之间的依赖关系(即一起工作的其它对象)只会通过以下几种方式来实现:
构造器的参数、工厂方法的参数,或给由构造函数或者工厂方法创建的对象设置属性。
因此,容器的工作就是创建bean时注入那些依赖关系。相对于由bean自己来控制其实例化、
直接在构造器中指定依赖关系或者类似服务定位器(Service Locator)模式这3种自主控制依赖关系注入
的方法来说,控制从根本上发生了倒转,这也正是控制反转(Inversion of Control, IoC) 名字的由来。

应用DI原则后,代码将更加清晰。而且当bean自己不再担心对象之间的依赖关系
(甚至不知道依赖的定义指定地方和依赖的实际类)之后,实现更高层次的松耦合将易如反掌。
DI主要有两种注入方式,即Setter注入和构造器注入
(5),在采用构造器注入的方式配置bean时,很有可能会产生循环依赖的情况。
比如说,一个类A,需要通过构造器注入类B,而类B又需要通过构造器注入类A。
如果为类A和B配置的bean被互相注入的话,那么Spring IoC容器将检测出循环引用,
并抛出 BeanCurrentlyInCreationException异常。
对于此问题,一个可能的解决方法就是修改源代码,将某些构造器注入改为setter注入。

(6),依赖配置详解
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">

<!-- results in a setDriverClassName(String) call -->
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
<property name="username" value="root"/>
<property name="password" value="masterkaoli"/>
</bean>

(7),各类数据类型的依赖注入

<bean id="moreComplexObject" class="example.ComplexObject">
<!-- results in a setAdminEmails(java.util.Properties) call -->
<property name="adminEmails">
<props>
<prop key="administrator">administrator@example.org</prop>
<prop key="support">support@example.org</prop>
<prop key="development">development@example.org</prop>
</props>
</property>
<!-- results in a setSomeList(java.util.List) call -->
<property name="someList">
<list>
<value>a list element followed by a reference</value>
<ref bean="myDataSource" />
</list>
</property>
<!-- results in a setSomeMap(java.util.Map) call -->
<property name="someMap">
<map>
<entry>
<key>
<value>an entry</value>
</key>
<value>just some string</value>
</entry>
<entry>
<key>
<value>a ref</value>
</key>
<ref bean="myDataSource" />
</entry>
</map>
</property>
<!-- results in a setSomeSet(java.util.Set) call -->
<property name="someSet">
<set>
<value>just some string</value>
<ref bean="myDataSource" />
</set>
</property>
</bean>

(8),自动装配
Spring IoC容器可以自动装配(autowire)相互协作bean之间的关联关系。
因此,如果可能的话,可以自动让Spring通过检查BeanFactory中的内容,
来替我们指定bean的协作者(其他被依赖的bean)。autowire一共有五种类型。
由于autowire可以针对单个bean进行设置,因此可以让有些bean使用autowire,有些bean不采用。

<bean id="waiter"
class="container.autowire.Waiter">
<property name="name"
value="宝玉"/>
</bean> <!-- 自动装配
byName:容器依据属性名查找对应的
bean,然后调用对应的set方法
来完成注入。
-->
<!--
<bean id="bar"
class="container.autowire.Bar"
autowire="byName"/>
-->
<!--
自动装配
byType:容器依据属性类型查找对应的
bean,然后调用对应的set方法
来完成注入。
注意:有可能有多个bean满足条件,会报错。
-->
<!--
<bean id="bar"
class="container.autowire.Bar"
autowire="byType"/>
-->
<!--
自动装配
constructor:
容器依据属性类型查找对应的
bean,然后调用对应的构造器
来完成注入。
注意:有可能有多个bean满足条件,
会报错。
-->
<bean id="bar"
class="container.autowire.Bar"
autowire="constructor"/>

(9)Bean的作用域
当一个bean的作用域为singleton, 那么Spring IoC容器中只会存在一个共享的bean实例,
并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。
Singleton作用域是Spring中的缺省作用域;(缺省就是默认)
singleton 只有一个实例,也即是单例模式。
prototype访问一次创建一个实例,相当于new。
应用场合:
1.需要回收重要资源(数据库连接等)的事宜配置为singleton,如果配置为prototype需要应用确保资源正常回收。
2.有状态的Bean配置成singleton会引发未知问题,可以考虑配置为prototype。

对于prototype作用域的bean,有一点非常重要,那就是Spring不能对一个prototype bean的整个生命周期负责:
容器在初始化、配置、装饰或者是装配完一个prototype实例后,将它交给客户端,随后就对该prototype实例不闻不问了。

(10)初始化web配置

要使用request、session和 global session作用域的bean(即具有web作用域的bean), 在开始设置bean定义之前,还要做少量的初始配置。请注意,假如你只想要“常规的”作用域,(singleton和prototype),就不需要这一额外的设置。

在目前的情况下,根据你的特定servlet环境,有多种方法来完成这一初始设置...

如果你用Spring Web MVC,即用SpringDispatcherServlet或DispatcherPortlet来处理请求,则不需要做特别的配置:DispatcherServlet 和 DispatcherPortlet已经处理了所有有关的状态

当使用了Spring's DispatcherServlet以外的Servlet 2.4及以上的Web容器时(如使用JSF或Struts),你需要在Web应用的'web.xml'文件中增加 javax.servlet.ServletRequestListener 定义

<web-app>
...
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
...
</web-app>
如果你用的是早期版本的web容器(Servlet 2.4以前的版本),那么你要使用一个javax.servlet.Filter的实现。请看下面的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>
RequestContextListener和RequestContextFilter两个类做的都是同样的工作: 将HTTP request对象绑定到为该请求提供服务的Thread。 这使得具有request和session作用域的bean能够在后面的调用链中被访问到。
Request作用域
考虑下面bean定义:

<bean id="loginAction" class="com.foo.LoginAction" scope="request"/>
针对每次HTTP请求,Spring容器会根据loginAction bean定义创建一个全新的LoginAction bean实例, 且该loginAction bean实例仅在当前HTTP request内有效,因此可以根据需要放心的更改所建实例的内部状态, 而其他请求中根据loginAction bean定义创建的实例,将不会看到这些特定于某个请求的状态变化。 当处理请求结束,request作用域的bean实例将被销毁。

Session作用域
考虑下面bean定义:

<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>
针对某个HTTP Session,Spring容器会根据userPreferences bean定义创建一个全新的userPreferences bean实例, 且该userPreferences bean仅在当前HTTP Session内有效。 与request作用域一样,你可以根据需要放心的更改所创建实例的内部状态,而别的HTTP Session中根据userPreferences创建的实例, 将不会看到这些特定于某个HTTP Session的状态变化。 当HTTP Session最终被废弃的时候,在该HTTP Session作用域内的bean也会被废弃掉。