通过实现 FactoryBean 接口注入 Bean
在 Spring 容器中有两类的 Bean,一类是普通的 Bean,一类是工厂 Bean。这两种 Bean 都是被 Spring 的容器进行管理的。而 Spring 也提供了一个接口用于扩展工厂 Bean,我们只要实现org.springframework.beans.factory.FactoryBean
即可。
使用FactoryBean
能够在 Spring 中更好更便捷地创建管理一些有着复杂构造逻辑的类对象。
如何使用
首先我们看一下FactoryBean
接口:
public interface FactoryBean<T> { T getObject() throws Exception; Class<?> getObjectType(); boolean isSingleton(); }
这三个方法的作用分别是:
getObject
:返回本工厂创建的对象实例getObjectType
:返回对象类型isSingleton
:表示被工厂创建的实例是否是单例
现在让我们开始使用,创建一个UserFactory
用来创建实例User
:
@Data public class User { private String name; private Integer age; }
UserFactory
工厂类:
public class UserFactory implements FactoryBean<User> { private String name; private Integer age; @Override public User getObject() throws Exception { return new User(name,age); } @Override public Class<?> getObjectType() { return User.class; } @Override public boolean isSingleton() { return true; } }
添加配置类将UserFactory
加入到容器中:
@Configuration public class FactoryBeanAppConfig { @Bean public UserFactory userFactory(){ UserFactory userFactory = new UserFactory(); userFactory.setAge(10); userFactory.setName("Grace"); return userFactory; } }
接下来我们就能通过UserFactory
工厂类进行创建User
了:
@SpringBootTest public class BeanFactoryTest { @Autowired private User user; @Test public void testBeanFactory(){ assertEquals(new Integer(10),user.getAge()); assertEquals("Grace",user.getName()); } }
此时我们 Debug 也能看到其我们自动注入的User
类就是通过UserFactory
创建的实例:
![]() |
加载顺序
有时候我们需要在getObject
方法执行之前执行一些动作,例如资源配置检查之类,此时我们可以使用@PostConstruct
注解在方法上,那么此方法就会在执行getObject()
方法执行之前先执行。
我们在UserFactory
工厂类中增加@PostConstruct
注解的方法,并且增加打印日志。
@Data public class UserFactory implements FactoryBean<User> { private String name; private Integer age; @Override public User getObject() throws Exception { System.out.println("getObject Begin"); return new User(name,age); } @Override public Class<?> getObjectType() { return User.class; } @Override public boolean isSingleton() { return true; } @PostConstruct public void Initialize(){ System.out.println("Initialize Begin"); } }
此时我们运行就会发现执行顺序:
Initialize Begin getObject Begin
AbstractFactoryBean 类
Spring 为我们提供了一个抽象类AbstractFactoryBean
为我们简化了操作。我们直接继承此类就能更加方便地创建单例或者非单例的实体类了。接下来我们就演示一下如何创建单例和非单例的类。首先先创建两个工厂,一个工厂SingleUserFactory
负责创建单例,一个工厂NonSingleUserFactory
负责创建非单例。
SingleUserFactory
类:
@Data public class SingleUserFactory extends AbstractFactoryBean<User> { private String name; private Integer age; @Override public Class<?> getObjectType() { return User.class; } @Override protected User createInstance() throws Exception { return new User(name,age); } }
NonSingleUserFactory
类:
@Data public class NonSingleUserFactory extends AbstractFactoryBean<User> { private String name; private Integer age; // 设置为非单例模式 public NonSingleUserFactory(){ setSingleton(false); } @Override public Class<?> getObjectType() { return User.class; } @Override protected User createInstance() throws Exception { return new User(name,age); } }
并且在配置类中配置这两个工厂 Bean:
@Bean(name = "singleUser") public SingleUserFactory getSingle(){ SingleUserFactory singleUserFactory = new SingleUserFactory(); singleUserFactory.setAge(12); singleUserFactory.setName("Single"); return singleUserFactory; } @Bean(name = "nonSingleUser") public NonSingleUserFactory getNonSingle(){ NonSingleUserFactory nonSingleUserFactory = new NonSingleUserFactory(); nonSingleUserFactory.setAge(12); nonSingleUserFactory.setName("NonSingle"); return nonSingleUserFactory; }
在测试类中测试如下:
public class SingleBeanFactoryTest extends BaseTest{ @Resource(name = "singleUser") private User user1; @Resource(name = "singleUser") private User user2; @Resource(name = "nonSingleUser") private User user3; @Resource(name = "nonSingleUser") private User user4; @Test public void testSingleBean(){ System.out.println(user1 == user2); System.out.println(user3 != user4); } }
true true
从结果中我们可以看到SingleUserFactory
工厂类创建的都是单例的对象,而NonSingleUserFactory
创建的都是非单例的对象。如果需要创建单例那么可以不设置singleton
的值,因为他是默认为true
的。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!