当前位置:首页 > 数码 > 容器启动有效的交互-Spring-如何利用-框架提供的才干-让-Bean-深化了解并与-Spring (容器启动过程)

容器启动有效的交互-Spring-如何利用-框架提供的才干-让-Bean-深化了解并与-Spring (容器启动过程)

admin7个月前 (04-16)数码38

Spring有一个特点,就是创立进去的Bean对容器是无感的,一个Bean是怎样样被容器从一个Class整成一个Bean的,关于Bean自身来说是不知道的,当然也不须要知道,也就是Bean对容器的存在是无感的。

Spring

然而有时刻咱们或者会遇到一些场景,这些场景让咱们去感知容器的存在,松哥举几个例子:

也就是说,只管Spring中的Bean可以不用去感知Spring容器的存在,然而在实践开发中,咱们往往还是须要Spring容器提供的各种才干,这样就迫使咱们的Bean不得不去感知到Spring容器的存在。

那么Spring中的Bean如何感知到Spring容器的存在呢?

Aware自身就有感知的意思。

SpringAware是Spring框架中的一个特性,它准许咱们的运行程序或组件与Spring容器启动交互。当一个类成功了SpringAware接口并注册到Spring容器中时,该类就能够感知到Spring容器的存在,并且可以失掉容器的一些资源或启动一些特定的操作。

SpringAware接口包含了多个子接口,每个子接口对应于不同的Spring容器资源或性能。

Aware的成功有很多,大的方向来说关键有如下一些:

图片

每一个Aware的作用如下:

经过成功这些接口,咱们可以在运行程序中失掉Spring容器提供的各种资源,并与容器启动交互,以成功更灵敏和可裁减的性能。

2.通常

举两个例子小同伴们来感触下Aware的详细用法。

2.1案例

例如我想在Bean中感知到以后Bean的名字,那么咱们可以依照如下模式来经常使用:

@ServicepublicclassUserServiceimplementsBeanNameAware{privateStringbeanName;@OverridepublicvoidsetBeanName(Stringname){this.beanName=name;}@OverridepublicStringtoString(){return"UserService{"+"beanName='"+beanName+'''+'}';}}

让以后bean成功BeanNameAware接口,偏重写setBeanName方法,这个方法会在Spring容器初始化Bean的时刻智能被调用,咱们就可以据此失掉到bean的称号了。

再比如我想做一个工具Bean,用来查找其余Bean,那么我可以经常使用如下模式:

@ComponentpublicclassBeanUtilsimplementsBeanFactoryAware{privatestaticBeanFactorybeanFactory;@OverridepublicvoidsetBeanFactory(BeanFactorybeanFactory)throwsBeansException{this.beanFactory=beanFactory;}publicstatic<T>TgetBean(Class<T>clazz){return(T)beanFactory.getBean(clazz);}}

让以后Bean成功BeanFactoryAware接口偏重写setBeanFactory方法,在系统初始化以后Bean的时刻,会智能调用setBeanFactory方法,进而将beanFactory变量传出去。

2.2原理

当Spring容器创立一个Bean的时刻,大抵的流程是 创立实例对象 -> 属性填充 -> Bean初始化

最后这个Bean的初始化,就是调用init方法、afterPropertiesSet方法以及BeanPostProcessor中的方法的,如下:

protectedObjectinitializeBean(StringbeanName,Objectbean,@NullableRootBeanDefinitionmbd){invokeAwareMethods(beanName,bean);ObjectwrappedBean=bean;if(mbd==null||!mbd.isSynthetic()){wrappedBean=applyBeanPostProcessorsBeforeInitialization(wrappedBean,beanName);}try{invokeInitMethods(beanName,wrappedBean,mbd);}catch(Throwableex){thrownewBeanCreationException((mbd!=null?mbd.getResourceDescription():null),beanName,ex.getMessage(),ex);}if(mbd==null||!mbd.isSynthetic()){wrappedBean=applyBeanPostProcessorsAfterInitialization(wrappedBean,beanName);}returnwrappedBean;}

在这个方法一出去,首先有一个invokeAwareMethods,这个就是用来触发Aware的,来看下:

privatevoidinvokeAwareMethods(StringbeanName,Objectbean){if(beaninstanceofAware){if(beaninstanceofBeanNameAwarebeanNameAware){beanNameAware.setBeanName(beanName);}if(beaninstanceofBeanClassLoaderAwarebeanClassLoaderAware){ClassLoaderbcl=getBeanClassLoader();if(bcl!=null){beanClassLoaderAware.setBeanClassLoader(bcl);}}if(beaninstanceofBeanFactoryAwarebeanFactoryAware){beanFactoryAware.setBeanFactory(AbstractAutowireCapableBeanFactory.this);}}}

小同伴们可以看到,BeanNameAware、BeanClassLoaderAware以及BeanFactoryAware这三种类型的Aware是在这里触发的。

每种Aware由于性能不同,因此作用的机遇也不同。

invokeAwareMethods方法执行终了之后,接上去是执行applyBeanPostProcessorsBeforeInitialization方法,这个咱们之前剖析过,这个方法最终会触发BeanPostProcessor#postProcessBeforeInitialization方法的执行,而BeanPostProcessor有一个子类专门处置Aware的,就是ApplicationContextAwareProcessor:

@Override@NullablepublicObjectpostProcessBeforeInitialization(Objectbean,StringbeanName)throwsBeansException{if(!(beaninstanceofEnvironmentAware||beaninstanceofEmbeddedValueResolverAware||beaninstanceofResourceLoaderAware||beaninstanceofApplicationEventPublisherAware||beaninstanceofMessageSourceAware||beaninstanceofApplicationContextAware||beaninstanceofApplicationStartupAware)){returnbean;}invokeAwareInterfaces(bean);returnbean;}privatevoidinvokeAwareInterfaces(Objectbean){if(beaninstanceofAware){if(beaninstanceofEnvironmentAwareenvironmentAware){environmentAware.setEnvironment(this.applicationContext.getEnvironment());}if(beaninstanceofEmbeddedValueResolverAwareembeddedValueResolverAware){embeddedValueResolverAware.setEmbeddedValueResolver(this.embeddedValueResolver);}if(beaninstanceofResourceLoaderAwareresourceLoaderAware){resourceLoaderAware.setResourceLoader(this.applicationContext);}if(beaninstanceofApplicationEventPublisherAwareapplicationEventPublisherAware){applicationEventPublisherAware.setApplicationEventPublisher(this.applicationContext);}if(beaninstanceofMessageSourceAwaremessageSourceAware){messageSourceAware.setMessageSource(this.applicationContext);}if(beaninstanceofApplicationStartupAwareapplicationStartupAware){applicationStartupAware.setApplicationStartup(this.applicationContext.getApplicationStartup());}if(beaninstanceofApplicationContextAwareapplicationContextAware){applicationContextAware.setApplicationContext(this.applicationContext);}}}

大家看下,这七种类型的Aware是在这里被触发的。

另外像ImportAware是在ImportAwareBeanPostProcessor#postProcessBeforeInitialization方法中处置的;LoadTimeWeaverAware是在、LoadTimeWeaverAwareProcessor#postProcessBeforeInitialization方法中处置的。

基本上,大局部的Aware接口都是在BeanPostProcessor中处置的。


spring怎么通过beanfactory来管理对象

首先先来理解spring中对JavaBean的管理机制。 Spring容器所管理的bean对象都是由beanFacotry工厂来实例化,所以要使用pring容器中bean实例对象,必须该类也是由spring容器所管理,否则无法从bean工厂中得到bean实例对象。 Struts 最新版本中是由 我们先抛开struts2专门来看spring,那么我们就从spring标准配置文件来说起,如果你要向某个由spring管理的对象中注入一个对象,我们该如何去做呢?举例说明:如果由两个对象A、B,现在需要在B对象中使用A对象,那么我们通过什么方式将A注入到B中去呢?首先A、B两个对象都必须是由spring容器来管理,那么我们就需要在配置文件定义property 属性来注入,现在A、B都有spring容器来管理的,那么我如何得到其中A对象呢?因为AB对象都是由spring容器来创建的,所以要想得到A对象,就首先得到BeanFactory--->GetA(),然后才能拿到A,这时A指向B对象的引用才有值,才能把A注入到B中。 1、 第一种不推荐的方式:在spring配置文件中配置如下:Java代码定义一个类变量(静态的static,这个类的所有实例共享的变量),启动服务器时,初始化spring时就创建了BeanFactory,在创建BeanFacotry时,就实例化了所有对象。 也就说也就创建了一个roleAssignmentHandler03 对象,放到了它自己容器的那块内存中,这个对象拥有一个指向userService的引用,因为我在这里定义的是类变量。 等下次在创建这个对象时,在这个类变量中同样是有值。 但是这种方法并不推荐,这种方式有点浪费内存空间,spring已经给我们创建了对象,但是我们并没有去使用它。 Java代码publicclassRoleAssignmentHandler03implementsAssignmentHandler{ privatestaticUserServiceuserService; publicvoidsetUserService(UserService_userService){ userService=_userService; } ……public class RoleAssignmentHandler03 implements AssignmentHandler {private static UserService userService;public void setUserService(UserService _userService) {userService = _userService;}……2、 第二种不推荐的方式:我不能向往常做测试那样通过new ClassPathXmlApplicationContext();来创建它,我们需要从当前环境中去拿,那么从什么地方去拿呢?那么就得明白它是如何创建的,由谁来创建并管理的?在服务器启动时,它就会初始化中的linstener配置信息,创建一个Bean’Factroy对象,并把这个对象放到了ServletContext中,我们可以利用spring中的一个工具类来得到ServletContext中的BeanFactory对象,但是并推荐,因为ServletActionContext是Struts中的,在业务逻辑中过分依赖于展现层的内容,JBPM是不依赖于展现层内容的,也不推荐于依赖关系的存在。 Java代码BeanFactoryfactory=(()); UserServiceuserService=(userService);BeanFactory factory = (());UserService userService = (userService);3、 第三种并不推荐的方式在项目开发中采用SSH与JBPM集成时,用到了一个第三方的集成包,我们可以从这里得到解决方案,(采用jbpm3.1所以其第三方集成包为)在其文档()中可以了解到,采用如下配置:流程定义文件配置Java代码 roleAssignmentHandler03 roleAssignmentHandler03在spring配置文件中可以这样定义如下Java代码 4、 第四种方式:回过头来,我们接着继续思考从BeanFactory中去获得,流程定义文件并不去修改它,这样就不会破坏它的灵活性,那么接下来要分析的问题就是如何来获得BeanFactory呢?那就得深入了解一下spring,现在来看一个问题:在一个单例中如何获得一个非单例的对象呢?也就是将B注入到A中 A是单例,但是B不是单例,直接采用Resource或在配置文件利用property注入的话,是无法实现的,只能将B变成一个单例对象来使用。 那么我们在单例对象中如何动态获取依赖对象呢?有一种方式就从它的BeanFactory中去获得其对象,如何在由spring管理的对象中拿到BeanFactory呢?也就是说在容器实例对象中访问容器本身,在spring中有这样一个BeanFactoryAware接口,在这个接口有个setBeanFactory(BeanFactory f)方法,我们可以实现该接口,重写这个方法,来得到我们BeanFactory,从中得到动态的得到BeanFactory中实例对象,但是放到jbpm中handler类中来使用,还是无法实现的,因为在这里它不是有spring来管理的,所以即使实现BeanFactory接口,重写其方法,但是无法将BeanFactory设置上值的,因为它是由spring来管理的,所以我无法从一个不是spring所管理的bean中去注入spring所提供的bean对象。 但是我们可以通过另一种途径来解决这个问题:创建一个辅助类BeanFactroyHelper类,让它来实现刚才这个BeanFactoryAware接口,具体如下:Java代码publicclassBeanFactoryHelperimplementsBeanFactoryAware{ privatestaticBeanFactoryfactory; publicvoidsetBeanFactory(BeanFactoryf)throwsBeansException{ factory=f; } publicstaticBeanFactorygetFactory(){ returnfactory; } }public class BeanFactoryHelper implements BeanFactoryAware {private static BeanFactory factory;public void setBeanFactory(BeanFactory f) throws BeansException {factory = f;}public static BeanFactory getFactory(){return factory;}}然后,让上面这个类纳入spring的管理,在spring中配置如下:Java代码 最后在我们handler类中,直接使用就可以了Java代码BeanFactoryfactory=();BeanFactory factory = ();这种方式可以,但是我并采用这种方式,因为第四种方式已经有人给我做了。 所以我们就不需要在重复做这些类似的工作了。 所以这种方式我也不会采用。 5、 第五种方式:通过上面所说的方式,在这个第三方集成包开发人中已经采用类似的方式实现了。 那么他们是如何实现的呢?这就需要来了解一下jbpmHandlerProxy的基本原理,在JbpmHandlerProxy类中实现了ActionHandler, AssignmentHandler, DecisionHandler, TaskControllerHandler等接口,在实现不同的接口会调用不同它的不同的方法execute、assign、decide…ServiceLocator,在spring中也提供了一个ServiceLocator这种设计模式的一个接口BeanFactoryLocator、 BeanFactoryReference接口,要想详细了解其内部机制需要我们进一步花费精力去解析其源码了。 (在这里就不详细去分析了)这里我只是了解jbpmFactoryPorxy类中实现机制的大体思想,所以下面我就针对在代理类中的具体实现思想大体说一下:在JbpmHandlerProxy类中得到BeanFactory对象,主要是通过JbpmFactoryLocator来得到BeanFactoryReference,通过BeanFactoryReference来得到Factory。 那么在JbpmHandlerProxy类中的JbpmFactoryLocator是从哪里得到的呢?查看源码可以得知在其JbpmFactoryLocator类下有个setBeanFactory()方法,那么这个方法是有谁调用的呢?通过查看得知是LocalJbpmConfigurationFactoryBean类来调用的。 主要分析图如下:以上就jbpmFactoryProxy中内部机制。 下面我就来说一下具体解决方案是:首先通过利用jbpmFactoryProxy的实现类中retrieveBeanFactory方法的具体实现方式,来得到jbpm中已经注入的BeanFactory对象,下面我将进一步进行封装来实现自动注入的功能。 先贴出在jbpm的handler类中的具体使用,和在spring中使用Bean对象一样使用。 Java代码/** *是由BaseAutowire自动注入 */@ResourceprivateUserServiceuserServce;/*** 是由BaseAutowire自动注入*/@Resourceprivate UserService userServce;下面一段代码将是所抽取出来的基类:Java代码/** *自动注入BeanFactory基类 *@authorlzh * */publicclassBaseAutowire{ /** *在调用子类的时会自动调用 *在构造方法中调用retrieveBeanFactory()方法得到BeanFactory对象 *利用它的实现接口设置将该自身设置为自动注入到子类中 */publicBaseAutowire(){ ((AutowireCapableBeanFactory)retrieveBeanFactory()) (this,_BY_TYPE,true); } protectedBeanFactoryretrieveBeanFactory(){ BeanFactoryLocatorfactoryLocator=newJbpmFactoryLocator(); BeanFactoryReferencefactory=(null); if(factory==null) thrownewIllegalArgumentException(nobeanFactoryfoundunderkey=+null); try{ (); } finally{ (); } } }/*** 自动注入BeanFactory基类* @author lzh**/public class BaseAutowire {/*** 在调用子类的时会自动调用* 在构造方法中调用retrieveBeanFactory()方法得到BeanFactory对象* 利用它的实现接口设置将该自身设置为自动注入到子类中*/public BaseAutowire() {((AutowireCapableBeanFactory)retrieveBeanFactory())(this, _BY_TYPE, true);}protected BeanFactory retrieveBeanFactory() {BeanFactoryLocator factoryLocator = new JbpmFactoryLocator();BeanFactoryReference factory = (null);if (factory == null)throw new IllegalArgumentException(no beanFactory found under key= + null);try {return ();}finally {();}}}

Spring Bean 框架有哪些用途?

Spring Bean框架是Spring框架的核心,它是一种容器,用于管理Java对象。 Spring Bean框架的主要用途是将Java对象封装成Spring Bean,然后在应用程序中使用Spring IoC容器来管理这些Bean。 这样可以使得应用程序更加模块化,易于维护和扩展。 Spring Bean框架提供了许多功能,包括:- 依赖注入(Dependency Injection):将依赖关系从代码中分离出来,使得代码更加灵活、可测试和可重用。 - 面向切面编程(Aspect-Oriented Programming):提供一种简化横切关注点(cross-cutting concerns)的方式,例如日志记录、安全性检查等。 - 声明式事务管理(Declarative Transaction Management):提供一种声明式的方式来管理事务,而不是通过编写繁琐的代码来实现。 - 事件处理(Event Handling):提供一种简单的方法来处理事件,例如使用@EventListener注解来监听事件。

免责声明:本文转载或采集自网络,版权归原作者所有。本网站刊发此文旨在传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及版权、内容等问题,请联系本网,我们将在第一时间删除。同时,本网站不对所刊发内容的准确性、真实性、完整性、及时性、原创性等进行保证,请读者仅作参考,并请自行核实相关内容。对于因使用或依赖本文内容所产生的任何直接或间接损失,本网站不承担任何责任。

标签: Spring

“容器启动有效的交互-Spring-如何利用-框架提供的才干-让-Bean-深化了解并与-Spring (容器启动过程)” 的相关文章

事务传播行为-Spring-七种类型一览 (spring事务传播行为)

事务传播行为-Spring-七种类型一览 (spring事务传播行为)

简介 Spring 事务传播性是指在 Spring 环境中,当多个包含事务的方法嵌套调用时,每个事务方法如何处理事务上下文中的提交或回滚行为。 传播性行为 Spring 中定义了 7 种事...

b-b-核心原理拆解与源码分析-2.0-Spring-Boot-深度实践 (核心b类期刊有哪些)

b-b-核心原理拆解与源码分析-2.0-Spring-Boot-深度实践 (核心b类期刊有哪些)

SpringBoot是一个基于Spring的轻量级框架,它简化了Spring应用程序的创建过程,使得开发者能够快速搭建一个可运行的应用程序。随着SpringBoot2.0版本的发布,其功能和性能得...

极致便当与卓越容错-Topic-Spring-重试-成功-运用-Kafka (极致餐是什么意思)

极致便当与卓越容错-Topic-Spring-重试-成功-运用-Kafka (极致餐是什么意思)

概述 Kafka的弱小性能之一是每个分区都有一个Consumer的偏移值。该偏移值是消费者将读取的下一条信息的值。可以智能或手动参与该值。假设咱们因为失误而不可处置信息并想重试,咱们可以选用...

Spring-Webflux-Boot-虚构线程性能逊色于-深化比较 (springboot)

Spring-Webflux-Boot-虚构线程性能逊色于-深化比较 (springboot)

早上看到一篇关于SpringBoot虚构线程和Webflux性能对比的文章,感觉还不错。内容较长,抓重点给大家引见一下这篇文章的外围内容,繁难大家极速浏览。 测试场景 作者驳回了一个尽...

Spring-Boot-Starter原理详解-b-b (springernature)

Spring-Boot-Starter原理详解-b-b (springernature)

SpringBoot Starter 是一种包含了一组特定功能和依赖关系的依赖项,旨在为特定的应用程序场景提供快速集成和开箱即用的功能。主要用于将常用的功能模块打包成一个可重用的依赖项,开发者只需...

使用Spring-Cloud和Java构建强大而灵活的微服务-十个实践案例 (使用spring框架的好处是什么)

使用Spring-Cloud和Java构建强大而灵活的微服务-十个实践案例 (使用spring框架的好处是什么)

在使用构建微服务时,许多人认为只要学习一些微服务设计模式就足够了,比如 CQRS、SAGA 或每个微服务一个数据库。虽然这是正确的,但同时学习一些通用的最佳实践也是很有意义的。本文分享一些最佳实践...

Scope及源码剖析-玩转Spring各种作用域Bean

Scope及源码剖析-玩转Spring各种作用域Bean

SpringScopeBean是Spring框架中用于治理Bean的作用域的机制,它定义了Bean的生命周期和实例化战略。经过正当地选用Bean的作用域,可以优化运行的性能和资源应用率。 环境:S...