Spring 容器
一. 组件注册
1. 给容器中注册组件
1.1 包扫描:
- @ComponentScan(value = ?): value里放包扫描的路径。
- @ComponentScans: 可以配置多个扫描的包
- excludeFilters=Filter[ ]:指定扫描包的时候按照什么规则排除哪些组件
@ComponentScan(value = "top.nnzi",excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class}),//按照注解排除
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {UserMapper.class}),//按照类型排除
@ComponentScan.Filter(type = FilterType.CUSTOM,classes = {})//自定义排除规则 class里是自定义排除规则的类,实现TypeFilter接口
})
- includeFilters=Filter[ ]:指定扫描包的时候要包含哪些组件,需将useDefaultFilters置false,使用和excludeFilters相似
@ComponentScan(value = "top.nnzi",includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class})
},useDefaultFilters = false)
1.2 容器中注册组件
- @Component、@Service、@Controller、@Repository、@Configuration 标注的类,主要是自己写的类
- @Bean:主要导入第三方的包里面的组件
- @Import:快速给容器中导入一个组件
- Import(类名):容器中就会自动注册这个组件,id默认是组件的全名
- ImportSelector:将返回值的类导入到容器
- ImportBeanDefinitionRegistrar:手动注册bean
@Import(MyImportSelector.class)
//MyImportSelector类实现ImportSelector接口,
//返回需要导入的组件的全类名的数组
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"top.nnzi.bean.User"};
}
}
- @Conditional({MyCondition.class}):标注在bean上,按照一定的条件判断,满足条件给容器中注册bean。
public class MyCondition implements Condition {
/**
*
* @param context 判断条件能使用的上下文(环境)
* @param metadata 注解信息
* @return true为允许注册,false反之
*/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//获取ioc使用的beanFactory
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//获取类加载器
ClassLoader classLoader = context.getClassLoader();
//获取当前环境信息
Environment environment = context.getEnvironment();
//获取bean定义的注册类
BeanDefinitionRegistry registry = context.getRegistry();
//逻辑代码编写,返回判断值.
return false;
}
}
- 使用Spring提供的FactoryBean(工厂bean):spring用来生产Bean到spring容器中。FactoryBean 通常是用来创建比较复杂的bean,一般的bean 直接用注解即可,但如果一个bean的创建过程中涉及到很多其他的bean 和复杂的逻辑,这时可以考虑用FactoryBean,很多开源项目在集成Spring 时都使用到FactoryBean
- 默认获取到的是工厂bean调用getObject创建的对象
- 要获取到工厂bean本身,需要给id前面加个&标识
public class UserFactoryBean implements FactoryBean<User> {
/**
*
* @return 返回一个对象,该对象会被添加到容器
* @throws Exception
*/
@Override
public User getObject() throws Exception {
return new User();
}
/**
*
* @return 返回对象的类型
*/
@Override
public Class<?> getObjectType() {
return User.class;
}
/**
*
* @return 是否为单实例创建 true表示单实例
*/
@Override
public boolean isSingleton() {
return false;
}
}
- @Scope():设置组件作用域
- prototype:多实例, ioc容器启动并不会去调用方法创建对象在容器中,而是每次获取时才会调用方法创建对象。
- singleton:单实例(默认值), ioc容器启动会调用方法创建对象放到ioc容器中,以后每次获取就是从容器中拿
- @Lazy:bean懒加载,不是在ioc容器启动的时候创建bean,而是当bean获取的时候创建
二. 生命周期
1. bean的生命周期
1.1 bean创建--初始化--销毁的过程:
- bean创建: 单实例:在容器启动时创建 多实例:每次获取时创建
- bean初始化:成员变量赋值,各种增强等,对象创建完成,并赋值好,调用初始化方法
- bean销毁 单实例:关闭容器时 多实例:容器不会管理这个bean,容器不会调用销毁方法
1.2 可以自定义初始化和销毁方法,容器在bean进行到当前声明周期的时候来调用我们自定义的初始化和销毁方法。
-
通过@Bean 指定init-method和destroy-method
-
通过让bean实现InitializingBean接口(定义初始化逻辑):在beanFactory将所有属性设置完成以后调用
-
-
通过让bean实现DisposableBean接口(定义销毁逻辑):在beanFactory销毁单实例对象前调用
-
-
可以使用JSR250注解:标注在方法上。 1、@PostConstructor:在bean创建完成并且属性赋值完成,来执行初始化方法 2、@PreDestroy:在容器销毁bean之前通知我们进行清理工作
-
BeanPostProcessor【接口】:bean的后置处理器:在bean初始化前后进行一些处理工作 (1) postProcessBeforeInitialization:在初始化之前进行一些工作 (2)postProcessAfterInitialization:在初始化之后进行一些工作
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
- BeanPostProcessor的大致执行流程:
- Spring底层对BeanPostProcess接口的使用 (1)BeanValidationPostProcessor用来实现数据校验 (2)AutowireAnnotationBeanPostProcessor,@Autowire实现 (3)ApplicationContextProcessor将容器注入到bean中 (4)InitDestroyAnnotationBeanPostProcessor会对@PostConstructor和@PreDestroy注解进行解析来达到容器的初始化和销毁方法的执行等等..
2.自动装配
- @AutoWired:自动注入【Spring定义的】:可以标注在构造器,参数,方法,属性
- Spring还支持使用@Resource(JSR250)和@Inject(JSR330)【java规范】
- 自定义组件想要使用Spring容器底层的一些组件(ApplicationContext,BeanFactory,xxx)自定义组件需要实现xxxAware接口;在创建对象的时候会调用接口规定的方法注入相关组件,把Spring底层的一些组件注入到自定义的bean中,xxxAware的功能都是使用xxxAwareProcessor处理的,判断实现了哪个Aware接口然后将bean转化为该类型调用set方法,将容器底层组件注入。
@Override
@Nullable
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
AccessControlContext acc = null;
if (System.getSecurityManager() != null &&
(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareInterfaces(bean);
return null;
}, acc);
}
else {
invokeAwareInterfaces(bean);
}
return bean;
}
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof Aware) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}
- @Profile:Spring为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能。 (1)加了环境标识的bean,只有这个环境被激活的时候才能注册到容器中,默认是default环境。 (2)写在配置类上,只有是指定的环境的时候,整个配置类里面的所有配置才能生效 (3)没有标注环境标识的bean在任何环境下都加载 运行时如何制定环境: (1)命令行参数,通过在虚拟机参数位置指定-Dspring.profiles.active=xxx来指定运行环境,标注了该环境的bean会被配置进容器中 (2)程序内指定:创建一个applicationContext ——》设置需要激活的环境,applicationContext.getEnvironment().setActiveProfiles("") ——》注册主配置类,applicationContext.register(xxx.class) ——》启动刷新容器,applicationContext.refresh();
四. AOP
五.声明式事务
- 给方法上面标注@Transactional 标识当前方法是一个事务方法
- @EnableTransactionManagement开启基于注解的事务管理功能
- 配置事务管理器来控制事务
@Bean
public PlatformTransactionManager platformTransactionManager (DateSource dateSource) {
return new DataSourceTransactionManager(dateSource);
}
六. BeanPostProcessor
BeanPostProcessor:bean后置处理器,bean创建对象初始化前后进行拦截工作的
- BeanFactoryPostProcessor:beanFactory的后置处理器,在beanFactory标注初始化后调用,所以bean的定义已经保存加载到beanFactory,但是bean的实例还未创建
流程:
- ioc容器创建对象
- invokeBeanFactoryPostProcessors(beanFactory):执行BeanFactoryPostProcessors
- String[] postProcessorNames =beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);找到所有postProcessor的名字执行方法
- 在初始化创建其它组件前面执行
BeanDefinitionRegistryPostProcessor: 是BeanFactoryPostProcessor的子接口,BeanDefinitionRegistry是Bean定义信息的保存中心,BeanFactory就是按照其中保存的bean的定义信息创建bean实例的。 postProcessBeanDefinitionRegistry()方法,在所有bean定义信息将要被加载到,但是bean实例还未创建,优先于BeanFactoryPostProcess执行,可以利用其给容器中再来添加一些组件
七. ApplicationListener
ApplicationListener:监听容器中发布的事件,事件驱动模型的开发 实现ApplicationListener< E extends ApplicationEvent >接口:监听ApplicationEvent及其子类的相关事件,只要容器中有相关事件发布,我们就能监听到这个事件,如
- ContextRefreshedEvent:容器刷新完成(所有bean都完全创建)会发布这个事件
- ContextClosedEvent:关闭容器发布这个事件
或者自己发布事件:自定义发布一个事件 ioc容器.publishEvent(ApplicationEvent);
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
/**
* Handle an application event.
* @param event the event to respond to
*/
void onApplicationEvent(E event);
}
注解形式: @EventListener(class={}):可以在普通业务逻辑组件的方法上标注该注解来监听事件。
八. Spring容器创建过程
Spring容器的refresh()【创建刷新】
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
1. BeanFactory的创建及预准备工作
- prepareRefresh()刷新前的预处理
- initPropertySources();初始化一些属性设置;子类自定义个性化属性设置方法;
- getEnvironment().validateRequiredProperties();检验属性的合法等;
- this.earlyApplicationEvents = new LinkedHashSet<>();保存容器中的一些早期事件
- ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory() 获取BeanFactory
- refreshBeanFactory();刷新【创建】beanFactory: 在GenericApplicationContext对象构造时this.beanFactory=new DefaultListableBeanFactory();并设置标识ID
- 通过getBeanFactory(); 返回刚才GenericApplicationContext创建的BeanFactory【DefaultListableBeanFactory】对象
- prepareBeanFactory(beanFactory);BeanFactory的预准备工作(BeanFactory进行一些设置):
- 设置BeanFactory的类加载器、支持表达式解析器
- 添加部分BeanPostProcessor【ApplicationContextAwareProcessor】
- 设置忽略的自动装配的接口EnvironmentAware、EmbeddedValueResolverAware...
- 注册可以解析的自动装配;我们能直接在任何组件中自动注入:BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext
- 添加BeanPostProcessor【ApplicationListenerDetector】
- 给BeanFactory中注册一些能用的组件: environment【ConfigurableEnvironment】、 systemPropertie【Map<String,Object>】、 systemEnvironment【Map<String,Object>】
- postProcessBeanFactory(beanFactory);BeanFactory准备工作完成后进行的后置处理工作
- 本身是一个空方法,子类通过重写这方法在BeanFactory创建并预准备完成以后做进一步的设置。
2.invokeBeanFactoryPostProcessors(beanFactory): 执行BeanFactoryPostProcessor的方法
BeanFactoryPostProcessor:BeanFactory的后置处理器,在BeanFactory标注初始化之后执行 有两个接口:BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor
- 执行invokeBeanFactoryPostProcessors方法
- 获取所有BeanDefinitionRegistryPostProcessor
- 先执行实现了PriorityOrdered优先级接口的、再执行实现了Ordered的接口的、最后执行其它的
- 获取所有BeanFactoryPostProcessor
- 先执行实现了PriorityOrdered优先级接口的、再执行实现了Ordered的接口的、最后执行其它的
3.registerBeanPostProcessors(beanFactory); 注册BeanPostProcessor
- BeanPostProcessor(Bean的后置处理器)【拦截Bean的创建过程】
- 不同类型的BeanPostProcessor,在Bean创建前后的执行时机是不一样的
有如下几类:
- BeanPostProcessor
- DestructionAwareBeanPostProcessor
- InstantiationAwareBeanPostProcessor
- SmartInstantiationAwareBeanPostProcessor
- MergedBeanDefinitionPostProcessor【internalPostProcessors】
- 执行流程:
- 获取所有的BeanPostProcessor; 后置处理器都默认可以通过PriorityOrdered、Ordered来指定优先级
- 先注册PriorityOrdered优先级接口的BeanPostProcessor 把每一个BeanPostProcessor添加到BeanFactory中, beanFactory.addBeanPostProcessor(postProcessor)
- 再注册了实现Ordered接口的
- 最后注册其它没有实现任何优先级接口的
- 最终注册MergedBeanDefinitionPostProcessor类型的
- 注册一个ApplicationListenerDetector;来在Bean创建完成后检查是否ApplicationListeneraddApplicationListener((ApplicationListener<?>) bean);
4. initMessageSource();初始化MessageSource组件(做国际化功能;消息绑定;消息解析等功能):
- 获取BeanFactory
- 看容器中是否有id为messageSource,类型是MessageSource的组件如果有赋值给messageSource,如果没有自己创建一个DelegatingMessageSource, MessageSource:取出国际化配置文件中的某个key的值;能按照区域信息获取
- 把创建好的MessageSource注册在容器中,以后获取国际化配置文件的值的时候,可以自动注入MessageSource;调用其方法可以获得相关配置属性 beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
5. initApplicationEventMulticaster();初始化事件派发器【多播器】
- 获取BeanFactory
- 从BeanFactory获取applicationEventMulticaster的组件
- 如果上一步没有配置;创建一个SimpleApplicationEventMulticaster
- 将创建的ApplicationEventMulticaster添加到BeanFactory中,以后其他组件直接自动注入 beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
6. onRefresh();留给子容器(子类)
- 空方法,子类重写这个方法,在容器刷新的时候可以自定义逻辑
7. registerListeners();给容器中将所有项目里面的ApplicationListener注册进来
- 从容器中拿到所有ApplicationListener组件
- 将每个监听器添加到事件派发器中 getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
- 派发之前步骤产生的事件
8. finishBeanFactoryInitialization(beanFactory);初始化所有剩下的单实例bean
beanFactory.preInstantiateSingletons();初始化剩下的单实例bean
- 获取容器中的所有Bean,依次进行初始化和创建对象 List beanNames = new ArrayList<>(this.beanDefinitionNames);
- 遍历beanNames获取bean 的定义信息; RootBanDefinition bd = getMergedLocalBeanDefinition(beanName);
- 判断Bean不是抽象的,是单实例的,不是懒加载得
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit())
- 判断是否是FactoryBean;是否是实现FactoryBean接口的Bean if (isFactoryBean(beanName))
- 如果是,利用工厂方法创建对象getObject();
- 不是工厂Bean,利用getBean(过程如下)(beanName);创建对象
- 所有Bean都利用getBean创建完成以后; 检查所有的Bean是否是SmartInitializingSingleton接口类型的,如果是就执行 afterSingletonsInstantiated()方法;
getBean过程: getBean(beanName);ioc.getBean;
- AbstractBeanFactory.doGetBean();
- 先获取缓存中保存的单实例bean,如果能获取到,说明这Bean之前被创建过(所有创建过的单实例Bean都会被缓存起来)从getSingleton方法中singletonObjects=new ConcurrentHashMap<String,Object>属性中获取到
- 缓存中获取不到,开始Bean的创建对象流程:
- 标记当前Bean已经被创建,markBeanAsCreated(beanName);防止多线程bean重复创建
- 获取Bean的定义信息:final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
- 获取当前Bean依赖的其它Bean;如果有,按照getBean()把依赖的Bean先创建出来
- 启动单实例Bean的创建流程:
单实例Bean的创建流程:
- createBean(beanName,mbd,args);
- Object bean = resolveBeforeInstantiation(beanName, mbdToUse);先让BeanPostProcessor【InstantiationAwareBeanPostProcessor】先拦截返回代理对象。先触发所有InstantiationAwareBeanPostProcessor接口的postProcessBeforeInstantiation()方法,如果有返回值调用postProcessAfterInstantiation()方法
- 如果没有返回bean,调用doCreateBean();Object beanInstance = doCreateBean(beanName, mbdToUse, args);
-
利用工厂方法或者对象的构造器等创建bean实例:createBeanInstance(beanName, mbd, args);
-
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
-
为bean的属性赋值:populateBean(beanName, mbd, instanceWrapper); 赋值之前:
- 拿到InstantiationAwareBeanPostProcessor类型的后置处理器,执行postProcessAfterInstantiation();
- 拿到InstantiationAwareBeanPostProcessor类型的后置处理器,执行postProcessProperties();
赋值:
- 应用Bean属性的值:为属性利用setter方法等进行赋值applyPropertyValues(beanName, mbd, bw, pvs);
-
bean初始化:initializeBean(beanName, exposedObject, mbd);(生命周期中介绍)
-
注册bean的销毁方法:registerDisposableBeanIfNecessary(beanName, bean, mbd);
-
- Bean的实例创建完成,将bean添加到缓存中:addSingleton(beanName, singletonObject);
ioc容器就是这些Map;很多Map里面保存了单实例bean,环境信息等...
9. finishRefresh();完成BeanFactory初始化创建工作;IOC容器就创建完成
- clearResourceCaches();清理一些资源缓存
- initLifecycleProcessor();初始化声明周期有关的后置处理器,允许我们写一个LifecycleProcessor的实现类,可以在BeanFactory进行到特定生命周期时进行调用 默认从容器中找是否有LifeCycleProcessor的组件,如果没有,默认会创建一个 new DefaultLifecycleProcessor();然后加入到容器中
- getLifecycleProcessor().onRefresh();拿到所有前面定义的生命周期处理器回调onRefresh()方法
- publishEvent(new ContextRefreshedEvent(this));发布容器刷新完成事件
- LiveBeansView.registerApplicationContext(this);
九. Spring容器创建总结
- Spring容器在启动的时候,先会保存所有注册进来的Bean的定义信息
- xml注册bean < bean id="" class = "">
- 使用注解;@Service、@Bean、@Component、...
- Spring容器会在合适的时机创建这些Bean
- 用到这个bean的时候,利用getBean方法创建bean,创建好以后保存在容器中
- 统一创建剩下所有bean的时候,即finishBeanFactoryInitialize();
- 后置处理器 每一个bean创建完成,都会使用各种后置处理器进行处理,来增强bean 的功能,如: + AutowiredAnnotationBeanPostProcessor会处理自动注入功能 + AnnotationAwareAspectJAutoProxyCreator来做AOP功能
- 事件驱动模型:
- ApplicationListener:事件监听
- ApplicationEventMulticaster:事件派发