【Spring入门-01】Bean

版权声明:LeifChen原创,转载请注明出处,谢谢~ https://blog.csdn.net/leifchen90/article/details/89955563

Spring Bean

作用域

  • singleton:一个 Bean 容器中只存在一个实例(Spring 默认作用域)
  • prototype:每次注入或者通过 Spring 应用上下文获取时都会创建一个单独的实例
  • request:每个 request 请求都会创建一个单独的实例
  • session:每个 session 都会创建一个单独的实例
  • application:每个 servletContext 都会创建一个单独的实例
  • websocket:每个 websocket 都会创建一个单独的实例
  • simpleThreadScope:每个线程都会创建一个单独的实例

singleton

使用 @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON) 注解标注 Bean 的作用域为 singleton ,则每次注入的 bean 都是同一个实例。

  • JavaConfig
@Configuration
public class ScopeBeanConfig {

    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
    public SingletonBean singletonBean() {
        return new SingletonBean();
    }
}

public class SingletonBean {
}
  • XML 配置
    <bean class="SingletonBean" scope="singleton"/>

prototype

使用 @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) 注解标注 Bean 的作用域为 prototype ,则每次注入或从 Spring 应用上下文获取的 bean 都会创建一个新的实例。

  • JavaConfig
@Configuration
public class ScopeBeanConfig {

    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public PrototypeBean prototypeBean() {
        return new PrototypeBean();
    }
}

public class PrototypeBean {
}
  • XML 配置
    <bean class="PrototypeBean" scope="prototype"/>

request

使用 @RequestScope 注解标注 Bean 的作用域为 request ,则每次 request 请求的 bean 都会创建一个新的实例。

  • JavaConfig
@Configuration
public class ScopeBeanConfig {

    @Bean
    @RequestScope
    public RequestBean requestBean() {
        return new RequestBean();
    }
}

public class RequestBean {
}
  • XML 配置
    <bean class="RequestBean" scope="request"/>

session

使用 @SessionScope 注解标注 Bean 的作用域为 session ,则会为每个 session 创建一个新的 bean 实例。

  • JavaConfig
@Configuration
public class ScopeBeanConfig {

    @Bean
    @SessionScope
    public SessionBean sessionBean() {
        return new SessionBean();
    }
}

public class SessionBean {
}
  • XML 配置
    <bean class="SessionBean" scope="session"/>

作用域代理

request/session 作用域的 bean(cart) 注入到 singleton 作用域的 bean(storeService) 时


@Configuration
public class ScopeBeanConfig {

    @Bean
    @SessionScope(proxyMode = ScopedProxyMode.INTERFACES)
    public Cart cart(){
        return new ShoppingCart();
    }

    @Bean
    public StoreService storeService(){
        return new StoreServiceImpl();
    }
}

public interface Cart {
}

public class ShoppingCart implements Cart {
}

public interface StoreService {
    void add();
}

public class StoreServiceImpl implements StoreService {

    @Autowired
    private Cart cart;

    @Override
    public void add() {
        System.out.println(cart.toString());
    }
}

singleton 作用域的 StoreService 在 Spring 应用上下文加载时实例化,同时试图将 Cart 构造注入。但是 session 作用域的 Cart 直到创建会话 session 后才会实例化。因此,Spring 会注入一个 Cart 的代理(暴露 Cart 中定义的方法),当 StoreService 调用 Cart 的方法时,代理会对其进行懒解析并调用委托给 session 作用域内真正的 Cart 。

通过 proxyMode 属性指定代理方式:

  • ScopedProxyMode.INTERFACES:基于 JDK 动态接口代理
  • ScopedProxyMode.TARGET_CLASS :基于 CGLib 代理

懒加载

Spring 容器会在创建容器时提前初始化 singleton 作用域的 Bean。但是如果 Bean 被标注了 lazy-init="true" ,则该 Bean 只有在其被需要的时候才会被初始化。

懒加载只对 singleton 作用域的 Bean 有效。
优点:节省资源
缺点:导致操作的响应时间增加

生命周期

初始化

如果需要在 Bean 实例化之后执行逻辑:

  1. 使用 init-method
public class Bean {
  public void init() {
    // To do
  }
}

通过 XML 配置

<bean class="Bean" init-method="init"/>

通过 JavaConfig

    @Bean(initMethod = "init")
    public Bean bean() {
        return new Bean();
    }
  1. 让 Bean 实现 org.springframework.beans.factory. InitializingBean 接口,覆盖 afterPropertiesSet 方法
public class Bean implements InitializingBean {
  @Override
  public void afterPropertiesSet() throws Exception {
    // To do
  }
}

销毁

如果需要在 Bean 销毁之前执行逻辑:

  1. 使用 destroy-method
public class Bean {

  public void destroy() {
    //To do
  }
}

通过 XML 配置

<bean class="Bean" init-method="destroy"/>

通过 JavaConfig

    @Bean(destroyMethod = "destroy")
    public Bean bean() {
        return new Bean();
    }
  1. 让 Bean 实现 org.springframework.beans.factory.DisposableBean 接口,覆盖 destroy 方法
public class Bean implements DisposableBean {
  @Override
  public void destroy() throws Exception {
    //To do
  }
}

配置全局默认初始化、销毁方法

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

     default-init-method="init" default-destroy-method="destroy">

</beans>

Bean 前置、后置处理器

如果想在 Spring IoC 容器完成 Bean 实例化、配置及初始化方法前后添加逻辑处理,可通过实现 BeanPostProcessor 接口定义的回调方法。此外,还可以通过实现 Ordered 接口提供的 order 属性来控制这些实现了 BeanPostProcessor 接口 Bean 处理器的执行顺序。

@Component
public class PostProcessor1 implements BeanPostProcessor, Ordered {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("Bean前置处理器1 before initialization");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("Bean后置处理器1 after initialization");
        return bean;
    }

    @Override
    public int getOrder() {
        return 1;
    }
}
@Component
public class PostProcessor2 implements BeanPostProcessor, Ordered {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("Bean前置处理器2 before initialization");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("Bean后置处理器2 after initialization");
        return bean;
    }

    @Override
    public int getOrder() {
        return 2;
    }
}
    <bean class="PostProcessor1"/>
    <bean class="PostProcessor2"/>

参考

  1. GitHub 代码
  2. Spring框架小白的蜕变
  3. Spring 实战(第4版)

猜你喜欢

转载自blog.csdn.net/leifchen90/article/details/89955563