厂家招总代理,seo技术培训茂名,帝国cms做视频网站性能如何,万网关网站三次优质博文#xff1a;IT-BLOG-CN
需求#xff1a; 使用autowired注入一些对象#xff0c;但发现不可以直接使用Autowired#xff0c;因为方法是static的#xff0c;要使用该方法当前对象也必须是static#xff0c;正常情况下Autowired无法注入静态的bean#xff0c;于是…优质博文IT-BLOG-CN
需求 使用autowired注入一些对象但发现不可以直接使用Autowired因为方法是static的要使用该方法当前对象也必须是static正常情况下Autowired无法注入静态的bean于是发现项目中用到了springContextHolder通过使用
private T t SpringContextHolder.getBean(T.class);或者我们在刚开始学习的时候会使用如下这种方式来获取Bean。但是这样就会存在一个问题因为它需要重新装载spring-core.xml文件并实例化上下文bean如果有些线程配置类也是在这个配置文件中那么会造成做相同工作的的线程会被启两次。一次是 web容器初始化时启动另一次是上述代码显示的实例化了一次。这样就产生了冗余。下面就来说说解决方案。
ApplicationContext appContext new ClassPathXmlApplicationContext(spring-core.xml);
T t (T)appContext.getBean(t); 一、SpringContextHolder 工具类
自定义SpringContextHolder工具类全网统一模板。需要将该类注入到Spring IOC中。因此路径很重要。
package com.zzx.utils;import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;/*** author* date*/
Component
Slf4j
public class SpringContextHolder implements ApplicationContextAware, DisposableBean {private static ApplicationContext applicationContext null;/*** 取得存储在静态变量中的ApplicationContext.*/public static ApplicationContext getApplicationContext() {assertContextInjected();return applicationContext;}/*** 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.*/public static T T getBean(String name) {assertContextInjected();return (T) applicationContext.getBean(name);}/*** 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.*/public static T T getBean(ClassT requiredType) {assertContextInjected();return applicationContext.getBean(requiredType);}/*** 检查ApplicationContext不为空.*/private static void assertContextInjected() {if (applicationContext null) {throw new IllegalStateException(applicaitonContext属性未注入, 请在applicationContext .xml中定义SpringContextHolder或在SpringBoot启动类中注册SpringContextHolder.);}}/*** 清除SpringContextHolder中的ApplicationContext为Null.*/public static void clearHolder() {log.debug(清除SpringContextHolder中的ApplicationContext: applicationContext);applicationContext null;}Overridepublic void destroy() throws Exception {SpringContextHolder.clearHolder();}Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {if (SpringContextHolder.applicationContext ! null) {log.warn(SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为: SpringContextHolder.applicationContext);}SpringContextHolder.applicationContext applicationContext;}
}二、ApplicationContextAware接口
Spring容器初始化的时候会检测容器中的所有Bean如果发现某个Bean实现了ApplicationContextAware接口Spring容器会在创建该Bean之后自动调用该Bean的setApplicationContextAware()方法调用该方法时会将容器本身作为参数传给该方法该方法将Spring传入的参数容器本身赋给该类对象的applicationContext实例变量因此接下来可以通过该applicationContext实例变量来访问容器本身。
三、BeanFactory
BeanFactory是Spring的“心脏”。它就是Spring IoC容器的真面目。Spring使用BeanFactory来实例化、配置和管理Bean。BeanFactory是IOC容器的核心接口它定义了IOC的基本功能我们看到它主要定义了getBean方法。getBean方法是IOC容器获取bean对象和引发依赖注入的起点。方法的功能是返回特定的名称的Bean。BeanFactory只能管理单例Singleton Bean的生命周期。它不能管理原型prototype非单例Bean的生命周期。这是因为原型Bean实例被创建之后便被传给了客户端,容器失去了对它们的引用。
BeanFactory的源码
public interface BeanFactory {// 用来引用一个实例或把它和工厂产生的Bean区分开就是说如果一个FactoryBean的名字为a那么a会得到那个Factory 四个不同形式的getBean方法获取实例Object getBean(String var1) throws BeansException;T T getBean(String var1, ClassT var2) throws BeansException;// 是否存在Object getBean(String var1, Object... var2) throws BeansException;T T getBean(ClassT var1) throws BeansException;T T getBean(ClassT var1, Object... var2) throws BeansException;T ObjectProviderT getBeanProvider(ClassT var1);T ObjectProviderT getBeanProvider(ResolvableType var1);boolean containsBean(String var1);// 是否为单实例boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;// 是否为原型多实例boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;// 名称、类型是否匹配boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;boolean isTypeMatch(String var1, Class? var2) throws NoSuchBeanDefinitionException;// 获取类型NullableClass? getType(String var1) throws NoSuchBeanDefinitionException;NullableClass? getType(String var1, boolean var2) throws NoSuchBeanDefinitionException;// 根据实例的名字获取实例的别名String[] getAliases(String var1);
}四、XmlBeanFactory
BeanFactory这是一个典型的工厂模式的工厂接口。BeanFactory最常见的实现类为XmlBeanFactory可以从classpath或文件系统等获取资源。
File file new File(fileSystemConfig.xml);
Resource resource new FileSystemResource(file);
BeanFactory beanFactory new XmlBeanFactory(resource);Resource resource new ClassPathResource(classpath.xml);
BeanFactory beanFactory new XmlBeanFactory(resource);我们通过在applicationContext.xml中配置
bean idcar classspring.ioc.demo.Car p:brandxiaopeng p:colorred p:maxSpeed520 /通过XmlBeanFactory实现启动Spring IoC容器
public static void main(String[] args) {// ResourcePatternResolver resolver new PathMatchingResourcePatternResolver();// Resource res resolver.getResource(classpath:applicationContext.xml);// BeanFactory factory new XmlBeanFactory(res); ApplicationContext factorynew ClassPathXmlApplicationContext(applicationContext.xml); Car car factory.getBean(car, Car.class);
}【1】XmlBeanFactory通过Resource装载Spring配置信息冰启动IoC容器然后就可以通过factory.getBean从IoC容器中获取Bean了。 【2】通过BeanFactory启动IoC容器时并不会初始化配置文件中定义的Bean初始化动作发生在第一个调用时。 【3】对于单实例singleton的Bean来说BeanFactory会缓存Bean实例所以第二次使用getBean时直接从IoC容器缓存中获取Bean。
五、ApplicationContext
如果说BeanFactory是Spring的心脏那么ApplicationContext就是完整的躯体了ApplicationContext由BeanFactory派生而来提供了更多面向实际应用的功能。在BeanFactory中很多功能需要以编程的方式实现而在ApplicationContext中则可以通过配置实现。
BeanFactorty接口提供了配置框架及基本功能但是无法支持spring的aop功能和web应用。而ApplicationContext接口作为BeanFactory的派生因而提供BeanFactory所有的功能。而且ApplicationContext还在功能上做了扩展相较于BeanFactortyApplicationContext还提供了以下的功能 【1】MessageSource提供国际化的消息访问 【2】资源访问如URL和文件 【3】事件传播特性即支持aop特性 【4】载入多个有继承关系上下文 使得每一个上下文都专注于一个特定的层次比如应用的web层
ApplicationContext是IOC容器另一个重要接口 它继承了BeanFactory的基本功能 同时也继承了容器的高级功能如MessageSource国际化资源接口、ResourceLoader资源加载接口、ApplicationEventPublisher应用事件发布接口等。
六、总结
【1】BeanFactroy采用的是延迟加载形式来注入Bean的即只有在使用到某个Bean时(调用getBean())才对该Bean进行加载实例化这样我们就不能发现一些存在的Spring的配置问题。而ApplicationContext则相反它是在容器启动时一次性创建了所有的Bean。这样在容器启动时我们就可以发现Spring中存在的配置错误。 相对于基本的BeanFactoryApplicationContext唯一的不足是占用内存空间。当应用程序配置Bean较多时程序启动较慢。 【2】BeanFacotry延迟加载如果Bean的某一个属性没有注入BeanFacotry加载后直至第一次使用调用getBean方法才会抛出异常而ApplicationContext则在初始化自身是检验这样有利于检查所依赖属性是否注入所以通常情况下我们选择使用ApplicationContext。 【3】应用上下文则会在上下文启动后预载入所有的单实例Bean。通过预载入单实例bean确保当你需要的时候你就不用等待因为它们已经创建好了。 【4】BeanFactory和ApplicationContext都支持eanPostProcessor、BeanFactoryPostProcessor的使用但两者之间的区别是BeanFactory需要手动注册而ApplicationContext则是自动注册。Applicationcontext比beanFactory加入了一些更好使用的功能。而且 beanFactory的许多功能需要通过编程实现而Applicationcontext可以通过配置实现。比如后处理beanApplicationcontext直接配置在配置文件即可而beanFactory这要在代码中显示的写出来才可以被容器识别。 【5】beanFactory主要是面对与spring框架的基础设施面对spring自己。而Applicationcontex主要面对与spring使用的开发者。基本都会使用Applicationcontex并非beanFactory。