当前位置: 首页 > 科技观察

Java工程师必须了解:什么是BeanFactory和FactoryBean?

时间:2023-03-14 01:02:41 科技观察

1。前提总结很多java开发者都见过Spring框架中后缀为FactoryBean的类,比如Mybatis-Spring中的SqlSessionFactoryBean。说到这里,不得不提一下BeanFactory。FactoryBean和BeanFactory特别容易混淆,面试经常会问到这两个概念。其实它们的功能和使用场景都不一样2.BeanFactory先说BeanFactory。用于访问Springbean容器的根接口。这是Springbean容器的基本客户端视图。原来是获取SpringBean的接口,也就是IoC容器。然后我们看类图,原来我们比较常用的ApplicationContext是一个BeanFactory。我们可以通过bean名称或类型从BeanFactory获取bean。BeanFactory的介绍相信大家并不陌生。让我们把注意力转向FactoryBean。3.什么是FactoryBeanFactoryBean?看看源码publicinterfaceFactoryBean{@NullableTgetObject()throwsException;@NullableClassgetObjectType();defaultbooleanisSingleton(){returntrue;}}TgetObject()获取泛型T实例。用于创建bean。当IoC容器通过getBean方法获取FactoryBean创建的实例时,实际获取的并不是FactoryBean本身,而是具体创建的T泛型实例。我们稍后会对此进行验证。ClassgetObjectType()获取TgetObject()中返回值T的具体类型。强烈建议如果T是接口,则返回其具体实现类的类型。defaultbooleanisSingleton()用于指定Factory创建的bean是否为单例。这里默认定义为单例方法。3.1FactoryBean的使用场景FactoryBean是用来创建一个类的bean。例如,你有一些属于鸟类的bean需要创建,但它们有自己的特点。你只需要将它们的特性注入到FactoryBean中,就可以生产出各种鸟的实例。举个更接近实际生产的例子。您甚至可以将此示例应用到实际的Java开发中。我们需要自己造一个定时任务的轮子。使用FactoryBean是完美的。下面我们一步步用代码说话来演示FactoryBean的使用场景。3.2构建一个FactoryBean我们声明定时任务一般有以下几个要素:时间段,肯定会用到cron表达式。用于执行任务的抽象接口。定时任务具体行为的执行者。Task任务实现了抽象接口的实现。实现包括两个方面:SomeService是具体任务的执行逻辑。cron时间表达式;}}通过上面的定义。任务时间和任务逻辑可以根据不同的业务进行不同的配置。然后我们在Task上实现一个FactoryBean。publicclassTaskFactoryBeanimplementsFactoryBean{privateSomeServicesomeService;privateStringcronExpression;@OverridepublicTaskgetObject()throwsException{CustomTaskcustomTask=newCustomTask(someService);customTask.setCron(cronExpression);returncustomTask;}@OverridepublicClassgetObjectType(){returnCustomTask.class;}@OverridepublicbooleanisSingleton(){returntrue;}publicSomeServicegetSomeService(){returnsomeService;}publicvoidsetSomeService(SomeServicesomeService){this.someService=someService;}publicStringgetCronExpression(){returncronExpression;}publicvoidsetCronExpression(StringcronExpression){this.cronExpression=cronExpression;}}3.3FactoryBean注入IoC你可以使用xml的注入方式,当然也可以使用javaConfig的配置方式。这里我们使用javaConfig注入。我们将两个FactroyBean注入到Spring容器中。@ConfigurationpublicclassConfig{@BeanpublicTaskFactoryBeancustomTask(){TaskFactoryBeantaskFactoryBean=newTaskFactoryBean();taskFactoryBean.setCronExpression("01510**?");Stringword="定时任务一";SomeServicesomeService=newSomeService();someService.setWord(word);taskFactoryBean.setSome(someService);returntaskFactoryBean;}@BeanpublicTaskFactoryBeanotherTask(){TaskFactoryBeanaskFactoryBean=newTaskFactoryBean();taskFactoryBean.setCronExpression("01517**?");Stringword="定时任务二";SomeServicesomeService=newSomeService();someService.setWord(word);taskFactoryBean.setSomeService(someService);returntaskFactoryBean;}}3.4FactoryBean的一些特性一般如上声明。如果@Bean注解没有显式声明bean名称,则使用方法名作为bean的名称,返回值作为注入的bean。但是我们通过调试发现:也就是说方法名返回的是FactoryBean创建的Bean。那么如何返回FactoryBean呢?上图中也给出了答案。在方法前添加引用字符“&”。具体原因可以从BeanFactory中查找。不是朋友不聚。我们测试了上面声明的两个bean,成功完成了不同定时任务的业务逻辑。@AutowiredprivateTaskcustomTask;@AutowiredprivateTaskotherTask;@Testpublicvoidtask(){customTask.execute();otherTask.execute();}4.总结在后续使用中,可以通过声明不同的cron表达式和不同的SomeServices定时任务来自定义更多。通过这个例子,相信你会对FactoryBean有一个清晰的认识。不提供演示。这很简单。强烈建议大家亲自尝试一下,加深理解。