IOC、IOC容器、Bean、DI
当我们需要使用对象的时候,我们一般会new来产生对象,但使用IoC思想后,我们获取对象不再是主动new对象,而是将该对象的创建控制权交给‘外部’,由‘外部’创建对象并交给我们。
IoC是一种思想,Spring对IoC进行了实现
Spring提供一个容器,名为IoC容器,充当IoC容器中的‘外部’
IoC容器存放了一个个的bean对象
IoC容器负责对象的创建,初始化等一系列工作
容器中建立bean与bean之间的依赖关系的整个过程,就叫做依赖注入
总结:DI可以认为是IoC的一种具体实现
对象已经能交给Spring的IOC容器来创建了,但是容器是如何来创建对象的呢?这就需要了解bean的实例化过程了
实例化bean可以通过配置文件来实现,但过于繁琐,下面所有内容将尽量使用注解来完成
顾名思义,bean其实就是一个对象,对象实例化自然就会调用自己的构造函数
使用@Componet注解
@Component("bookDao")
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ..." );
}
}
之前没使用注解的时候,需要手动在配置文件中配置,使用完注解后,只需要配置spring的扫描包路径,就会达到和在配置文件中定义bean一样的效果
注意:Spring底层使用的是无参构造函数来实例化bean的。
首先,我们需要创建一个配置类,并在这个类上添加@Configuration注解:
@Configuration
public class AppConfig {
// ...
}
然后,在这个配置类中添加一个工厂方法,并在这个方法上添加@Bean注解:
@Configuration
public class AppConfig {
@Bean
public MyBean myBean() {
return new MyBean();
}
// ...
}
静态的工厂方法
public class MyBeanFactory {
public static MyBean createMyBean() {
// 创建并返回MyBean实例的代码
}
}
最后
@Configuration
public class AppConfig {
@Bean
public MyBean myBean() {
return MyBeanFactory.createMyBean();
}
// ...
}
Bean的生命周期注意可以分为五个部分:1.Bean的实例化,2.设置属性,3.Bean的初始化方法,4.使用,5.销毁
上文已经讲述不再赘述了
依赖注入指的是建立bean与bean之间的依赖关系,设置属性有三种方式:1.属性注入(Autowire),2.setter注入,3.构造器注入
属性注入
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class MyClass {
@Autowired(required = false)
private MyDependency myDependency;
// ... 其他代码 ...
}
setter注入
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class MyClass {
private MyDependency myDependency;
@Autowired
public void setMyDependency(MyDependency myDependency) {
this.myDependency = myDependency;
}
// ... 其他代码 ...
}
构造器注入
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class MyClass {
private MyDependency myDependency;
@Autowired
public MyClass(MyDependency myDependency) {
this.myDependency = myDependency;
}
// ... 其他代码 ...
}
总结:实例化和初始化的区别
实例化和属性设置是 Java 级别的系统“事件”,其操作过程不可⼈⼯⼲预和修改;⽽初始化是给开发者
提供的,可以在实例化之后,类加载完成之前进⾏⾃定义“事件”处理。
1.实现了各种 Aware 通知的⽅法,如 BeanNameAware、BeanFactoryAwared,ApplicationContextAware
例如:
public class MyBeanFactory implements BeanFactoryAware {
private BeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
public void getMyBeanName() {
MyBeanName myBeanName = beanFactory.getBean(MyBeanName.class);
System.out.println(beanFactory.isSingleton("myCustomBeanName"));
}
}
通过beanFactory我们就可以手动获取IoC容器中的bean了
ApplicationContextAware 的接⼝⽅法
@Component
public class ApplicationContextUtil implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static ApplicationContext getApplicationContext(){
return context;
}
}
作用和BeanFactoryAware接口类似,都是获取spring上下文
2.执⾏ BeanPostProcessor 初始化前置⽅法
public class MyBeanPostProcessor implements BeanPostProcessor{
/**
* 实例化、依赖注入完毕,在调用显示的初始化之前完成一些定制的初始化任务
* 注意:方法返回值不能为null
* 如果返回null那么在后续初始化方法将报空指针异常或者通过getBean()方法获取不到bena实例对象
* 因为后置处理器从Spring IoC容器中取出bean实例对象没有再次放回IoC容器中
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("初始化 before--实例化的bean对象:"+bean+"\t"+beanName);
// 可以根据beanName不同执行不同的处理操作
return bean;
}
/**
* 实例化、依赖注入、初始化完毕时执行
* 注意:方法返回值不能为null
* 如果返回null那么在后续初始化方法将报空指针异常或者通过getBean()方法获取不到bena实例对象
* 因为后置处理器从Spring IoC容器中取出bean实例对象没有再次放回IoC容器中
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("初始化 after...实例化的bean对象:"+bean+"\t"+beanName);
// 可以根据beanName不同执行不同的处理操作
return bean;
}
}
BeanPostProcessor主要作用于初始化方法执行前后
3.执⾏ @PostConstruct 初始化⽅法,依赖注⼊操作之后被执⾏;
4.执⾏⾃⼰指定的 init-method ⽅法(如果有指定的话);
5.执⾏ BeanPostProcessor 初始化后置⽅法。
见上述第二条
使用不用多说,bean销毁前也会执行一些销毁方法
销毁容器的各种⽅法,如 @PreDestroy、DisposableBean 接⼝⽅法、destroy-method。
@PreDestroy==DisposableBean
@Component
public class MyBean implements DisposableBean {
// ...
@Override
public void destroy() throws Exception {
// 执行清理操作
System.out.println("MyBean销毁前执行清理操作");
}
}
以上就是我对SpringIoC容器的见解,如有错误望指正!