对于这种区别,其实最好的答案是看他的使用上,因为有些东西的界限并不是预先设定好的,反而是他本身才是他的定义,我们先这两个接口的定义代码:
org.springframework.beans.factory.FactoryBean
这里有必要说明一下@FunctionalInterface的使用,@FunctionalInterface注解是jdk8才出现的,他的作用是编译期约束检查接口,该注解只能作用于interface,不能作用于其他类型,经此注解修饰的接口有且只能有一个抽象方法,可以有静态方法,也可以有default方法,注意,Java interface中的方法都是默认public abstract的,你不要写这两个多余的修饰符。
这个注解是为函数式编程而生的,也就是实现此接口的实参可以是lambda表达式,当然也可以是一个class类型。
这个接口是一个非常普通的对象工厂,就是提供一个创建对象的模式。
@FunctionalInterface
public interface ObjectFactory<T> {
/**
* Return an instance (possibly shared or independent)
* of the object managed by this factory.
* @return the resulting instance
* @throws BeansException in case of creation errors
*/
T getObject() throws BeansException;
}
org.springframework.beans.factory.ObjectFactory
public interface FactoryBean<T> {
String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
@Nullable
T getObject() throws Exception;
@Nullable
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
}
再来看看他们的使用,这里我们直接使用Spring中的源码:
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#addSingletonFactory
这里的第二个参数是一个函数接口类型的,我们需要看看实参传递的是什么
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
实参传递:这里就是传递了一个lambda表达式,其实是一个函数。
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}