Spring IOC要义

Spring IOC要点
1、beans的scope配置默认为singleton,配置要点是:use the prototype scope for all stateful beans and the singleton scope for stateless beans.
2、与其他scope不同,spring并不会对prototype执行完整的声明周期管理,spring文档说明如下:although initialization lifecycle callback methods are called on all objects regardless of scope, in the case of prototypes, configured destruction lifecycle callbacks are not called. The client code must clean up prototype-scoped objects and release expensive resources that the prototype bean(s) are holding. To get the Spring container to release resources held by prototype-scoped beans, try using a custom bean post-processor, which holds a reference to beans that need to be cleaned up.
3、singleton bean依赖注入一个prototype bean,由于具有不同的生命周期管理,依赖关系只会在初始化时执行一次,因此,如果想在运行期持续的获取一个新的protype bean实例,不能仅仅是在一个singleton bean中dependency-inject一个prototype bean. If you need a new instance of a prototype bean at runtime more than once, see Section 4.4.6, “Method injection”,You can make bean A aware of the container by implementing the ApplicationContextAware interface, and by making a getBean("B") call to the container ask for (a typically new) bean B instance every time bean A needs it. The following is an example of this approach:

// a class that uses a stateful Command-style class to perform some processing
package fiona.apple;

// Spring-API imports
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class CommandManager implements ApplicationContextAware {

 private ApplicationContext applicationContext;

 public Object process(Map commandState) {
    // grab a new instance of the appropriate Command
    Command command = createCommand();
    // set the state on the (hopefully brand new) Command instance
    command.setState(commandState);
    return command.execute();
 }

 protected Command createCommand() {
    // notice the Spring API dependency!
    return this.applicationContext.getBean("command", Command.class);
 }

 public void setApplicationContext(ApplicationContext applicationContext)
                                                                  throws BeansException {
    this.applicationContext = applicationContext;
 }
}

4、Scoped beans as dependencies
   The Spring IoC container manages not only the instantiation of your objects (beans), but also the wiring up of collaborators (or dependencies). If you want to inject (for example) an HTTP request scoped bean into another bean, you must inject an AOP proxy in place of the scoped bean. That is, you need to inject a proxy object that exposes the same public interface as the scoped object but that can also retrieve the real, target object from the relevant scope (for example, an HTTP request) and delegate method calls onto the real object.

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

  <!-- an HTTP Session-scoped bean exposed as a proxy -->
  <bean id="userPreferences" class="com.foo.UserPreferences" scope="session">

        <!-- instructs the container to proxy the surrounding bean -->
        <aop:scoped-proxy/>
  </bean>

  <!-- a singleton-scoped bean injected with a proxy to the above bean -->
  <bean id="userService" class="com.foo.SimpleUserService">

      <!-- a reference to the proxied userPreferences bean -->
      <property name="userPreferences" ref="userPreferences"/>

  </bean>
</beans>

5、选择代理类型
  By default, when the Spring container creates a proxy for a bean that is marked up with the <aop:scoped-proxy/> element, a CGLIB-based class proxy is created. This means that you need to have the CGLIB library in the classpath of your application.

Note: CGLIB proxies only intercept public method calls! Do not call non-public methods on such a proxy; they will not be delegated to the scoped target object.

Alternatively, you can configure the Spring container to create standard JDK interface-based proxies for such scoped beans, by specifying false for the value of the proxy-target-class attribute of the <aop:scoped-proxy/> element. Using JDK interface-based proxies means that you do not need additional libraries in your application classpath to effect such proxying. However, it also means that the class of the scoped bean must implement at least one interface, and that all collaborators into which the scoped bean is injected must reference the bean through one of its interfaces.

<!-- DefaultUserPreferences implements the UserPreferences interface -->
<bean id="userPreferences" class="com.foo.DefaultUserPreferences" scope="session">
  <aop:scoped-proxy proxy-target-class="false"/>
</bean>

<bean id="userManager" class="com.foo.UserManager">
  <property name="userPreferences" ref="userPreferences"/>
</bean>

6、管理bean的生命周期
   在Spring 2.5以后, 有三种方法来管理 bean生命周期行为: the InitializingBean and DisposableBean callback interfaces; custom init() and destroy() methods; and the @PostConstruct and @PreDestroy annotations. You can combine these mechanisms to control a given bean.
    同一个bean的生命周期管理使用了多种生命周期管理机制,如果不同的管理机制使用了不同的方法名,则不同的配置方法将按照下面的顺序分别执行,如果不同的管理机制使用的是相同的方法名,则方法只会执行一次。
Multiple lifecycle mechanisms configured for the same bean, with different initialization methods, are called as follows:

    Methods annotated with @PostConstruct

    afterPropertiesSet() as defined by the InitializingBean callback interface

    A custom configured init() method

Destroy methods are called in the same order:

    Methods annotated with @PreDestroy

    destroy() as defined by the DisposableBean callback interface

    A custom configured destroy() method