Spring强大的FactoryBean还能这样用,涨知识

开发 前端
FactoryBean 接口是 Spring IoC 容器实例化逻辑的一个可插入点。如果你有复杂的初始化代码,而这些代码最好用 Java 而不是冗长的 XML 来表达,那么你可以通过自定义自己的 FactoryBean,在该类中编写复杂的初始化,然后将自定义 FactoryBean 添加到容器中。

环境:Spring6.1.7

1. 简介

FactoryBean 接口是 Spring IoC 容器实例化逻辑的一个可插入点。如果你有复杂的初始化代码,而这些代码最好用 Java 而不是冗长的 XML 来表达,那么你可以通过自定义自己的 FactoryBean,在该类中编写复杂的初始化,然后将自定义 FactoryBean 添加到容器中。

FactoryBean<T> 接口提供了三种方法:

  • T getObject(): 返回该工厂创建的对象的实例。该实例可能是共享的,这取决于该工厂返回的是单体还是原型
  • boolean isSingleton(): 如果此 FactoryBean 返回单例,则返回 true;否则返回 false。此方法的默认实现返回 true。
  • Class<?> getObjectType(): 返回 getObject() 方法返回的对象类型,如果事先不知道类型,则返回空值。

FactoryBean接口在Spring框架非多的地方被使用。Spring本身就包含了50多个FactoryBean接口的实现。

2. 实战案例

准备基本类;

class PersonService {
  public void save() {
     // TODO
     System.out.println("save person...") ;
  }
}

接下来会基于上面的PersonService类进行FactoryBean各种案例的使用;

2.1 简单示例

自定义FactoryBean<PersonService>实现;

@Component
public class PersonServiceFactoryBean implements FactoryBean<PersonService> {
  // 具体的实例
  public PersonService getObject() throws Exception {
    PersonService ps = new PersonService() ;
    return ps ;
  }
  // 具体的类型
  public Class<?> getObjectType() {
    return PersonService.class ;
  }
  // true,返回单例容器中只会有一个PersonService
  public boolean isSingleton() {
    return true ;
  }
}

具体使用;

// 你可以直接在其它的Bean中注入
@Resource    
private PersonService personService ;
// 你可以通过BeanFactory手动获取
private ApplicationContext contet ;
PersonService ps = context.getBean(PersonService.class) ;

使用时和普通的Bean的使用方式一致。

2.2 多例&不指定类型

多例;

如果你需要每次使用时返回的都是不同的实例对象,那么你可以将isSingleton返回为false。

// 将上面的isSingleton返回为false
public boolean isSingleton() {
  return false ;
}

接下来使用时,不管是在其它组件中进行注入还是通过getBean获取,都能确保在每个组件中使用的都不是同一个实例。

@Component
public class PersonController {
  @Resource
  private PersonService personService ;
}
@Component
public class CommonService {
  @Resource
  private PersonService personService ;
}

上面两个类中注入的PersonService将不是同一个实例,如果你通过getBean获取每次也都不是同一个实例。

不指定类型;

如果你将FactoryBean#getObjectType方法返回为null。那么你将无法正确的注入PersonService对象,同时程序将抛出异常

图片图片

2.3 创建代理

你可以通过FactoryBean创建代理对象借助ProxyFactory。将getObject修改如下:

public PersonService getObject() throws Exception {
  ProxyFactory factory = new ProxyFactory() ;
  factory.setTarget(new PersonService()) ;
  factory.addAdvice(new MethodInterceptor() {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
      System.out.println("before...") ;
      return invocation.proceed() ;
    }
  }) ;
  return (PersonService) factory.getProxy() ;
}

通过FactoryBean能够非常方便的以编程的方式创建代理对象。

2.4 获取原始FactoryBean

如果你需要获取FactoryBean本身,而非getObjectType类型,那么你可以通过如下方式:

// 方式1:直接通过类型获取
private ApplicationContext context ;
context.getBean(PersonServiceFactoryBean.class) ;
// 方式2:通过beanName获取,但是需要添加'&'前缀
context.getBean("&psFactoryBean") ;

上面2种方式都能正确的获取原始的FactoryBean对象。

2.5 利用SPI获取对象

Spring为我们提供了ServiceFactoryBean类,通过该类我们能非常方便的获取SPI对象并注册为容器Bean。

@Configuration
public class AppConfig {
  @Bean
  public ServiceFactoryBean serviceFactoryBean() {
    ServiceFactoryBean fb = new ServiceFactoryBean() ;
    // 指定SPI接口类型
    fb.setServiceType(DAO.class) ;
    return fb ;
  }
}

接下来你就可以在META-INF/services下建立DAO全限定名的文件

com.pack.bean.create.PersonDAO
com.pack.bean.create.StudentDAO

当在容器中注入DAO时,你将得到这里的第一个PersonDAO实例。

责任编辑:武晓燕 来源: Spring全家桶实战案例源码
相关推荐

2022-08-12 08:25:33

Python异常信息代码

2024-05-17 09:37:26

format属性Spring

2018-01-22 10:52:43

前端CSS追踪用户

2023-12-29 08:17:20

接口类SpringAOP

2021-10-29 07:49:22

Spring事务管理

2019-01-29 10:00:59

GitHub开源搜索

2020-10-12 06:28:05

动态IP框架

2023-03-30 11:38:56

机器学习逻辑规则数量

2020-11-16 13:38:31

PostMessage

2021-07-28 06:10:47

拖拽设计器 transmat

2021-09-05 07:55:37

前端Emoji 表情

2019-03-28 11:07:56

Spring BootRedis缓存

2021-03-02 10:50:23

SpringMVC 参数JavaWeb

2012-07-13 11:32:16

网络出口

2024-08-02 08:38:20

Controller接口地址

2020-09-14 11:26:54

BinlogCanal数据库

2024-04-25 11:45:09

在线地图SOTA

2017-12-07 14:21:57

存储方式变迁

2023-07-06 14:24:23

Spring接口自定义

2023-10-27 07:39:44

IOC容器Spring
点赞
收藏

51CTO技术栈公众号