IOC的底层原理:XML解析+工厂模式+反射
public class UserService {
/**
* 之前想要在一个类中使用另一个类的实例方法,就必须创建此类的对象,然后调用,
* 但是这样的话,两个类的耦合度就太高了,如果实现类要换了,
* 所有类用到了这个实现类的都要改,这里的new UserDao();都得改,
* 改的话就意味着要重新编译,打包,部署,这样耗费的人力就太多了.
*
* 于是spring就站出来,提出一种解决方案:IOC控制反转.
* spring说不要将对象定死了,就是不要程序员自己创建对象了,程序员只需要声明即可,
* 对象由spring创建,然后放在容器中供我们使用.
*/
// private UserDao userDao = new UserDaoImpl(); 不要自己创建对象
@Autowired
private UserDao userDao;// 只需声明即可,这样代码就不用修改了
public int addUser(){
int add = userDao.add();
return add;
}
}
1、首先就是bean实例化,调用bean的无参或有参构造器创建对象。
2、调用setter方法给bean对象的属性赋值,如果第一步是调用有参的构造器创建对象,这步就没有。
3、spring调用Aware接口中的方法,凡是实现了Aware接口的类,都会执行接口中的方法
/**
* User bean
*
* BeanFactory, ApplicationContext等对象是spring容器的内置对象,不是程序员定义的。
* 如果想要在一个bean中使用这些对象的话,可以在bean中声明想要的容器内置对象:private ApplicationContext applicationContext;
*
* 然后实现xxxAware接口,实现接口的方法,这样在bean初始化的时候,spring会调用xxxAware接口的setXXX(XXX xxx),将你想要对象作为方法的对象传过来,
* 然后你就可以用这个对象了。
*
* @author shkstart
* @create 2022-09-05 11:33
*/
public class User implements ApplicationContextAware {
// 在一个bean中想要用ApplicationContext对象,
private ApplicationContext applicationContext;
// applicationContext对象spring调用这个方法的时候会传过来
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("2、Aware接口的setApplicationContext()给User对象的applicationContext属性赋值...");
this.applicationContext = applicationContext;
}
}
4、bean初始化前置处理:spring调用BeanPostProcessor接口中的postProcessBeforeInitialization(Object bean, String beanName)
bean就是你的bean对象,beanName是你的bean对象的name,这是你就可以对你的bean对象做任何操作,这个阶段是为了给你的bean一些扩展处理。
如果你想对你的bean对象在初始化前做一些自定义的处理,就可以实现BeanPostProcessor接口,并实现postProcessBeforeInitialization(Object bean, String beanName)方法。
5、执行InitializingBean接口中的afterPropertiesSet()方法
看方法名是在属性设置完后,就是在bean对象属性设置完之后由spring调用,和上面那个初始化前置处理区别就只是,这个方法没有参数,不能对bean对象做处理,只能做一些额外的逻辑处理。想要用,bean类要实现InitializingBean接口。
6、执行程序员自定义的初始化方法。
// 自定义初始化方法
@PostConstruct
public void initUser(){
System.out.println("User对象初始化时,执行...");
}
7、 bean初始化后置处理:执行BeanPostProcessor接口中的postProcessAfterInitialization(Object bean, String beanName)方法。
如果你想对你的bean对象在初始化后做一些自定义的处理,就可以实现BeanPostProcessor接口,并实现postProcessAfterInitialization(Object bean, String beanName)方法。
8、经过上面的3~7的bean初始化,这个时候bean就可以使用了,使用完了如果容器关闭,就进入bean销毁阶段。
1)bean销毁前置处理:执行DestructionAwareBeanPostProcessor接口中的postProcessBeforeDestruction(Object bean, String beanName)方法,如果想要在bean销毁前对bean对象做一些处理,可以实现这个接口。
2)执行自定义的销毁方法,不想在销毁前对bean对象做处理,只是做一些额外的业务处理,可以自定义销毁方法,不带参数。
// 自定义销毁回调方法
@PreDestroy
public void destroyUser(){
System.out.println("容器关闭,User对象销毁前...");
}