Spring

Posted 深蓝

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring相关的知识,希望对你有一定的参考价值。

1. Spring的BeanFactory和FactoryBean的区别

    1. Spring的BeanFactory是顶层接口,定义了Spring容器的基本功能,ApplicationContenxt是BeanFactory的子接口,加强了BeanFactory,增加了读取配置文件和国际化等功能

      BeanFactory
          -> ApplicationContenxt 子级接口
          -> ClassPathXmlApplicationContenxt 基于XML的配置
          -> FileSystemXmlApplicationContenxt 
          -> AnnotationConfigApplicationContenxt 注解配置
    1. FactotyBean是一种构造复杂Bean的方式的接口,可以自定义Bean的细节并加入Spring管理

2. Bean的生命周期

  1. 初始化Bean
  2. 注入属性值
  3. 如果实现BeanNameAware接口,调用BeanNameAwaresetBeanName传入当前Bean的ID
  4. 如果实现BeanFactoryAware接口,调用BeanFactoryAwaresetBeanFactory传入当前工厂实例的引用
  5. 如果实现ApplicationContextAware接口,调用ApplicationContextAwaresetApplicationContext传入当前ApplicationContext实例的引用
  6. 如果有Bean的前置初始化处理器,调用postProcessBeforeInitialization执行处理
  7. 如果实现InitializingBean接口,调用InitializingBeanafterPropertiesSet方法
  8. 调用init方法进行初始化
  9. 如果有Bean的后置初始化处理器,调用postProcessAfterInitialization执行处理
  10. 如果作用范围是单例,则加入Ioc缓存池,否则结束
  11. 当ApplicationContext容器关闭时,调用设定的preDestorydestory执行销毁
/**
 * 注解将Bean加入IOC
 */
@Configuration
@ComponentScan({"com.pal.entity"})
public class SpringConfig {

    @Bean(value = "PoDemo",initMethod = "init",destroyMethod = "destroy")
    public PoDemo getInstance(){
        PoDemo poDemo = new PoDemo();
        poDemo.setName("poDemo");
        return poDemo;
    }
}
/**
 * 除process拦截器外的生命周期方法
 */
public class PoDemo implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean {

    private String name;
    private Integer age;

    @Override
    public void setBeanName(String name) {
        System.out.println("3.注册我成为Bean时定义的ID:"+name);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("4.管理此Bean的BeanFactory为:"+beanFactory);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("5.管理此Bean的ApplicationContext为:"+applicationContext);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("7.属性设置之后执行 afterPropertiesSet()");
    }

    public void init() {
        System.out.println("8.Bean的Init方法被执行");
    }
    
    @PreDestroy
    public void preDestroy() {
        System.out.println("10.销毁Bean之前执行preDestroy");
    }

    public void destroy() {
        System.out.println("11.调用destroy方法销毁Bean");
    }
  
  
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}
/**
 * 拦截实例化、属性注入之后的对象
 */
@Component
public class BeanPostProcessorDemo implements BeanPostProcessor {

    /**
     * Init方法执行前的操作
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if ("PoDemo".equalsIgnoreCase(beanName))
        {
            System.out.println("6.Init方法前的处理!");
        }
        return null;
    }

    /**
     * Init方法执行后的操作
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if ("PoDemo".equalsIgnoreCase(beanName))
        {
            System.out.println("9.Init方法后的处理!");
        }
        return null;
    }
}
/**
 * 启动方法
 */
@Test
void BeanLifeTest() {
    // 在config类中将Bean加入管理用
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
    PoDemo poDemo = (PoDemo) applicationContext.getBean("PoDemo");
    System.out.println("加载Bean -> "+poDemo.getName());
    applicationContext.close();
}

3. Bean加载方式

2.1 XML方式

// 通常引入xml方式
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
BeanClass bean = applicationContext.getBean("beanId");
<!-- Spring ioc 实例化Bean的三种方式 -->
<!-- 一:使用无参构造器(推荐) -->
<bean id = "beanId" class = "com.lagou.xxx."></bean>

<!-- 另外两种是为了将new的对象加入spring管理 -->
<!-- 二:静态方法 -->
<bean id = "beanId" class = "com.lagou.xxx.xxxFactory" factory-method = "getInstance"></bean>
public class Factory{
    public static XXBean getinstance(){
        return new XXBean();
    }
}

<!-- 三:实例化方法 -->
<bean id = "factoryBeanId" class = "com.lagou.xxx.xxxFactory"></bean>
<bean id = "beanId" factory-bean = "factoryBeanId" factory-method = "getInstance"></bean>
public class Factory{
    public XXBean getinstance(){
        return new XXBean();
    }
}

3. Bean的作用范围与生命周期

3.1 作用范围

  • Singleton -> 单例 bean对象生命周期与容器相同。
  • Prototype -> 多例 bean对象,spring框架只负责创建,不负责销毁(JVM回收)。
  • Request,session
<bean id = "beanId" class = "com.lagou.xxx." scope = "xxx"></bean>

以上是关于Spring的主要内容,如果未能解决你的问题,请参考以下文章

Spring boot:thymeleaf 没有正确渲染片段

What's the difference between @Component, @Repository & @Service annotations in Spring?(代码片段

spring练习,在Eclipse搭建的Spring开发环境中,使用set注入方式,实现对象的依赖关系,通过ClassPathXmlApplicationContext实体类获取Bean对象(代码片段

Spring Rest 文档。片段生成时 UTF-8 中间字节无效 [重复]

解决spring-boot启动中碰到的问题:Cannot determine embedded database driver class for database type NONE(转)(代码片段

一张图帮你记忆,Spring Boot 应用在启动阶段执行代码的几种方式