@scope 申明bean的作用范围

1. 创建Car

public class Car {
	private String name;
	private int price;
	
	public Car(){
		System.out.println("car constructor...");
	}
}

2.将Car放入bean中管理

public class MainConfig {
    @Bean
    public Car car(){
        System.out.println("add bean car into spring");
        return new Car();
    }
}

3.启动spring容器

@Test
    public  void test04(){
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        System.out.println("IOC started");
     
    }

运行结果如下

因此spring注册组件默认是在创建IOC容器的时候创建的

将启动spring容器的代码中创建两个car

@Test
    public  void test04(){
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        System.out.println("IOC started");
        Car car1 = applicationContext.getBean(Car.class);
        Car car2 = applicationContext.getBean(Car.class);
        System.out.println(car1==car2);
    }

运行结果如下

因此,可知bean默认是单例的。在创建IOC容器的时候创建的,每当获取的时候都是同一个实例。

当在配置中添加@Lazy的时候,对相应的组件将会实行懒加载。调用的时候才会去实现初始化。

配置修改如下

public class MainConfig {

    @Bean
    @Lazy
    public Car car(){
        System.out.println("add bean car into spring");
        return new Car();
    }
}

运行结果如下

从结果可看出,懒加载的时候。调用时才回去加载bean。并且只加载一次。

spring有如下四种作用域

prototype:多实例的:ioc容器启动并不会去调用方法创建对象放在容器中。
每次获取的时候才会调用方法创建对象;
singleton:单实例的(默认值):ioc容器启动会调用方法创建对象放到ioc容器中。
以后每次获取就是直接从容器(map.get())中拿,
request:同一次请求创建一个实例
session:同一个session创建一个实例

可以用@Scope申明Bean的生命周期

修改配置成如下

public class MainConfig {

    @Scope("prototype")
    @Bean
    public Car car(){
        System.out.println("add bean car into spring");
        return new Car();
    }

再次运行

由结果可知。原型模式。spring初始化的时候并未去加载bean。而是在每次调用的时候再去加载。为多实例。

 

Spring bean的生命周期

bean的生命周期:bean创建—初始化----销毁的过程
容器管理bean的生命周期:我们可以自定义初始化和销毁方法;容器在bean进行到当>前生命周期的时候来调用我们自定义的初始化和销毁方法

1.指定初始化和销毁方法

在申明组件的时候,加上初始化和销毁的方法

public class Car  {
	private String name;
	private int price;
	
	public Car(){
		System.out.println("car constructor...");
	}
	
	public void init(){
		System.out.println("car ... init...");
	}
	
	public void destroy(){
		System.out.println("car ... destroy...");
	}

}

  通过@Bean指定init-method和destroy-method

public class MainConfig {
    @Bean(initMethod = "init",destroyMethod = "destroy")
    public Car car(){
        System.out.println("add bean car into spring");
        return new Car();
    }
}

开启和销毁容器

 @Test
    public  void test04(){
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        System.out.println("IOC started");
        Car car1 = applicationContext.getBean(Car.class);

        ((AnnotationConfigApplicationContext) applicationContext).close();
    }

运行结果如下图

由图可知:在组件创建的时候init方法被调用。在组件销毁的时候,destroy方法被调用。

当组件被申明为原型模式

public class MainConfig {

    @Scope("prototype")
    @Bean(initMethod = "init",destroyMethod = "destroy")
    public Car car(){
        System.out.println("add bean car into spring");
        return new Car();
    }

运行结果如下图所示

从结果可看出,如果bean是多实例,spring只负责创建Bean,在容器关闭时并不销毁bean。

实现InitializingBean(定义初始化逻辑) DisposableBean(定义销毁逻辑)

代码如下

public class Car implements InitializingBean, DisposableBean {
	private String name;
	private int price;
	
	public Car(){
		System.out.println("car constructor...");
	}
	
	@Override
	public void destroy(){
		System.out.println("car ... destroy...");
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println("car ... afterPropertiesSet...");

	}
}

运行结果如下

BeanPostProcessor

BeanPostProcessor,针对所有Spring上下文中所有的bean,配置一个BeanPostProcessor,然后对所有的bean进行一个初始化之前和之后的代理。BeanPostProcessor接口中有两个方法: postProcessBeforeInitialization和postProcessAfterInitialization。 postProcessBeforeInitialization方法在bean初始化之前执行, postProcessAfterInitialization方法在bean初始化之后执行。 

1.创建MyBeanPostProcessor继承BeanPostProcessor接口,重写postProcessBeforeInitialization和postProcessAfterInitialization两个方法。

public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("------------------------------");
        System.out.println("对象------" + beanName + "postProcessBeforeInitialization-----"+bean);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("------------------------------");
        System.out.println("对象-----" + beanName + "postProcessAfterInitialization-----"+bean);
        return bean;
    }
}

2.将MyBeanPostProcessor加入容器管理

@Configuration
public class MainConfig {
    @Bean(initMethod = "init",destroyMethod = "destroy")
    public Car car(){
        System.out.println("add bean car into spring");
        return new Car();
    }
    
    @Bean
    public MyBeanPostProcessor myBeanPostProcessor(){
        return new MyBeanPostProcessor();
    }
}

3.启动spring容器

   @Test
    public  void test04(){
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        System.out.println("IOC started");
        Car car1 = applicationContext.getBean(Car.class);

        ((AnnotationConfigApplicationContext) applicationContext).close();
    }

运行结果如下图

由结果可知:在每个bean的初始化前后都调用了BeanPostProcessor