main方法单元测试:
public static void main(String[] args) { MyFactoryBean factoryBean = new MyFactoryBean(UserService.class, new UserServiceImpl()); UserService userService = (UserService) factoryBean.getObject(); System.out.println(userService.sayHello()); } private interface UserService { String sayHello(); } private static class UserServiceImpl implements MyFactoryBean.UserService { @Override public String sayHello() { return "hello world"; } }
控制台输出:
16:17:05.330 [main] DEBUG com.fsx.single.temp.MyFactoryBean - invoke method......sayHello 16:17:05.334 [main] DEBUG com.fsx.single.temp.MyFactoryBean - invoke method before......1545121025334 16:17:05.334 [main] DEBUG com.fsx.single.temp.MyFactoryBean - invoke method after......1545121025334 hello world
ObjectFactory
通过接口内容来看,两者都是属于工厂模式用来创建对象使用的。
啥都不说,先看个例子吧:
@Configuration public class RootConfig { @Bean public FactoryBean myFactoryBean() { return new MyFactoryBean(); } @Bean public ObjectFactory myObjectFactory() { return new MyObjectFactory(); } public static class MyFactoryBean implements FactoryBean<Daughter> { @Override public Daughter getObject() throws Exception { return new Daughter(); } @Override public Class<?> getObjectType() { return Daughter.class; } } public static class MyObjectFactory implements ObjectFactory<Son> { @Override public Son getObject() throws BeansException { return new Son(); } } } @Autowired private ApplicationContext applicationContext; @Autowired private RootConfig.MyFactoryBean myFactoryBean; @Autowired private RootConfig.MyObjectFactory myObjectFactory; @Autowired private Daughter daughter; //@Autowired //这里son不能直接注入,但是上面的daughter可以,因为它是FactoryBean,Spring在Bean初始化时会对其进行支持处理 //private Son son; @ResponseBody @GetMapping("/hello") public String helloGet() throws Exception { // 这里注意一下:ApplicationContext是可以直接注入的,可谓非常的方便(至于原因:原理的博文里有说) System.out.println(applicationContext); //WebApplicationContext for namespace 'dispatcher-servlet': s ... System.out.println(applicationContext.getParent()); //Root WebApplicationContext: startup date [Tue Mar 05 //======================================== System.out.println(myFactoryBean); //com.fsx.config.RootConfig$MyFactoryBean@1f8bccbb // 这样子,我们是能拿到一个对象的。但需要注意:每get一次,就是new了一个新的 System.out.println(myObjectFactory.getObject()); //com.fsx.bean.Son@309e3495 System.out.println(daughter); //com.fsx.bean.Daughter@6cb10346 // 需要注意的是:单独自己去get的话,出来的都是不同的对象(因此此工厂Bean,Spring又没有增强,所以铁定会执行方法体) System.out.println(myFactoryBean.getObject() == myFactoryBean.getObject()); //false System.out.println(myObjectFactory.getObject() == myObjectFactory.getObject()); //false return "hello...Get"; }
从上面的现象打印值的不同,可以看出FactoryBean和ObjectFactory最直接的区别。上面已经介绍了FactoryBean,这里简单先介绍下
ObjectFactory:
ObjectFactory则只是一个普通的对象工厂接口。在查看AbstractBeanFacotry的doGetBean(…) 部分的源码时,可以看到spring对ObjectFactory的应用之一就是,将创建对象的步骤封装到ObjectFactory中 交给自定义的Scope来选择是否需要创建对象来灵活的实现scope
区别:
FactoryBean的着重于自定义创建对象过程,由BeanFactory通过FactoryBean来获取目标对象,而如果是isSingleton返回true的话,spring会利用单例缓存来缓存通过FactoryBean创建的对象。
而ObjectFactory就是一个普通的工厂对象接口,对于spring在doGetBean处的使用时,在于创建对象的过程由框架通过ObjectFactory定义,而创建的时机交给拓展接口Scope,除此之外ObjectFactory就是一个普通的接口
此外在将给依赖注入列表注册一个ObjectFactory类型的对象,在注入过程中会调用objectFactory.getObject()来创建目标对象注入进去。(如beanFactory.registerResolvableDependency(HttpSession.class, new SessionObjectFactory());)
简单来说就是通过FactoryBean你可以控制对象如何创建,而ObjectFactory借助Scope接口自定义scope你可以控制对象的创建时机