1)spring容器俯瞰
图片来自网络
spring启动时,先加载bean的配置信息,读取到spring容器的Bean定义注册表中,然后根据Bean注册表实例化Bean,装配好Bean之间的依赖关系,再然后将Bean放到spring容器中,最后由应用程序读取使用。
容器加载Bean的原理
- BeanDefinitionReader读取Resource所指向的配置文件资源,然后解析配置文件。配置文件中每一个<bean>解析成一个BeanDefinition对象,并保存到BeanDefinitionRegistry中;
- 容器扫描BeanDefinitionRegistry中的BeanDefinition;调用InstantiationStrategy进行Bean实例化的工作;使用BeanWrapper完成Bean属性的设置工作;
- 单例Bean缓存池:Spring 在 DefaultSingletonBeanRegistry 类中提供了一个用于缓存单实例 Bean 的缓存器,它是一个用 HashMap 实现的缓存器,单实例的 Bean 以 beanName 为键保存在这个HashMap 中。
容器启动原理:Spring应用的IOC容器通过tomcat的Servlet或Listener监听启动加载;Spring MVC的容器由DispatchServlet作为入口加载;Spring容器是Spring MVC容器的父容器
2)Spring IOC原理概述
根据松耦合少入侵原则,new对象时与该原则在很多时候是相冲突的,并且可能一些不好的习惯导致对象不能释放。比较优的一种方式是面向接口编程。见下列
public class StudentServiceImpl {
//class
private StudentDaoImpl studentDaoImpl;
public void oldCode(){
//原来的做法
StudentDaoImpl=new studentDaoImpl();
studentDaoImpl.add();
}
}
//=================new====================
public class StudentServiceImpl {
//interface
private StudentDao StudentDaoImpl;
public void newCode(){
//变为面向接口编程
StudentDaoImpl=new studentDaoImpl();
studentDaoImpl.add();
}
}
比较新旧两种方式,面向接口编程的好处是显而易见的,因为当修改或者替换StudentImpl时,只需要使Student接口指向一个新的实现类即可。但是还是有弊端,当修改dao的实现类时,仍然要修改service。最好的方式就是不修改service而达到修改dao的目的。利用反射可以实现该目的:根据给出的完整类名来动态的创建对象,这种方式让类只有在生成时才决定是哪一种对象。因此可以通过假设,在某个配置文件写好了StudentDaoImpl的完全限定名称,然后通过反射来动态的创建该类。
通过该原理,再来理解IOC就容易理解多了。spring IOC也是一个对象,在某个特定的时间创建好之后,可以实现对其他对象的控制,初始化、创建、销毁等。可以简单的理解为,只需要将要创建的类的全限定名配置好告知springIOC,他就会动态的帮我们创建对象。通过这种控制反转的设计模式(IOC)实现了松耦合,这种方式使得一个对象依赖其他对象时也会动态的关联创建出来,如service包含了dao,其依赖的dao会被自动注入进来,而不是手动创建这些类。可以把IOC看做是工厂模式的升级版,只不过对象都是在XML里面定义的,获取类名,利用反射技术,生成相应的对象。
3)spring容器装载bean
首先在XML文件中声明类的全限定名之后,通过ClassPathXmlApplicationContext去加载,获取相应的实例调用相应的方法。也可以采用注解的方式
@Configuration
public class BeanConfiguration {
@Bean
public AccountDao accountDao(){
return new AccountDaoImpl();
}
@Bean
public AccountService accountService(){
AccountServiceImpl bean=new AccountServiceImpl();
//注入dao
bean.setAccountDao(accountDao());
return bean;
}
}
使用注解@Configuration相当于XML中的<beans>标签。在该类中,每一个@Bean注解对应着一个<bean>标签。
spring依赖注入:所谓依赖注入即是,当一个bean实例引用另外一个bean实例时,spring帮助创建另外一个bean实例,并注入到当前的bean中。
4)Bean的生命周期:
- Bean实例的创建(getBean->createBean)
- 为Bean实例设置属性(populateBean)
- 初始化Bean(initializeBean)
- Bean 被应用使用
- 容器关闭时,Bean销毁(destoryMethod)