在之前讲解Spring系列-依赖注入实现原理-注解配置的时候,在解析依赖resolveDependency()方法中已经碰到过了ObjectFactory和ObjectProvider,在那里我们说了它们可以解决懒加载以及依赖注入为null的问题,这一节我们就来详细讲讲这两个类。
接口定义
ObjectFactory
我们先来看一下ObjectFactory的接口定义:
@FunctionalInterface
public interface ObjectFactory<T> {
T getObject() throws BeansException;
}
通过类名我们可以知道这是一个对象工厂,那肯定是用来生产对象的。而且我们发现该接口是一个函数式接口,只有一个方法定义getObject()用于返回一个对象实例。
看到getObect()方法不知道大家有没有感到很熟悉?没错,在FactoryBean中也有一个getObject()方法,只不过FactoryBean虽然也可以通过getObject()方法获取一个对象,但是FactoryBean本质上一个Bean,它在Spring中非常特殊,Spring对它进行了单独的处理。如果我们通过BeanName获取Bean时,发现该Bean是一个FactoryBean,那么Spring会自动调用FactoryBean的getObject()方法,然后将该方法返回的对象实例返回,如果我们就想获取FactoryBean实例,那么我们需要在BeanName的前面加上&符号,详细流程我们已经在Spring系列-Spring的Bean创建流程介绍过了。
ObjectProvier
我们再来看一下ObjectProvider的接口定义:
public interface ObjectProvider<T> extends ObjectFactory<T>, Iterable<T> {
// 返回用指定参数创建的bean, 如果容器中不存在, 则抛出异常
T getObject(Object... args) throws BeansException;
// 如果指定类型的在Bean中存在, 返回bean实例, 否则返回null
@Nullable
T getIfAvailable() throws BeansException;
// 如果返回对象不存在,则用传入的Supplier获取一个Bean并返回,否则直接返回存在的对象
default T getIfAvailable(Supplier<T> defaultSupplier) throws BeansException {
T dependency = getIfAvailable();
return (dependency != null ? dependency : defaultSupplier.get());
}
// 消费对象的一个实例,如果存在通过Consumer回调消耗目标对象, 如果不存在则直接返回
default void ifAvailable(Consumer<T> dependencyConsumer) throws BeansException {
T dependency = getIfAvailable();
if (dependency != null) {
dependencyConsumer.accept(dependency);
}
}
// 如果不可用或不唯一(没有指定primary)则返回null。否则,返回对象
@Nullable
T getIfUnique() throws BeansException;
// 如果不存在唯一对象,则调用Supplier的回调函数
default T getIfUnique(Supplier<T> defaultSupplier) throws BeansException {
T dependency = getIfUnique();
return (dependency != null ? dependency : defaultSupplier.get());
}
// 如果存在唯一对象,则消耗掉该对象
default void ifUnique(Consumer<T> dependencyConsumer) throws BeansException {
T dependency = getIfUnique();
if (dependency != null) {
dependencyConsumer.accept(dependency);
}
}
// 返回符合条件的对象的Iterator,没有特殊顺序保证(一般为注册顺序)
@Override
default Iterator<T> iterator() {
return stream().iterator();
}
// 返回符合条件对象的连续的Stream,没有特殊顺序保证(一般为注册顺序)
default Stream<T> stream() {
throw new UnsupportedOperationException("Multi element access not supported");
}
// 返回符合条件对象的连续的Stream。在标注Spring应用上下文中采用@Order注解或实现Order接口的顺序
default Stream<T> orderedStream() {
throw new UnsupportedOperationException("Ordered element access not supported");
}
}
同样通过类名我们可以知道这也是一个用于提供对象实例的工厂类,与ObjectFactory不同的是,它继承了ObjectFactory接口,并实现了Iterable接口,说明它扩展了OjbectFactory提供了更加丰富的功能。
Spring应用场景
将ObjectFactory作为回调函数使用
在AbstractBeanFactory中的doGetBean()方法中进行使用。
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
// ...
if (mbd.isSingleton()) {
// 这里的getSingleton()方法的第二个参数就是ObjectFactory类型
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}else if (mbd.isPrototype()) {
// ...
}else {
String scopeName = mbd.getScope();
Scope scope = this.scopes.get(scopeName);
try {
// 这里的scope.get()方法的第二个参数也是ObjectFactory类型
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
// ...
return (T) bean;
}
使用ObjectFactory类型进行依赖注入
注入ObjectFactory类型
这样如果实际要注入的Bean不存在,在使用时才会报错。
依赖注入
@Component
public class Home {
// 注入的类型为ObjectFactory, 通过user.getObject()获取真正的UserBean对象,如果不存在会报错
@Autowired
private ObjectFactory<User> user;
}
解析依赖注入
// DefaultListableBeanFactory.java
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
// 如果是ObjectFactory类型或者ObjectProvider类型,创建一个DependencyObjectProvider对象返回,该类实现了ObjectProvider接口,实现了getObject()等方法
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
注册解析可解析依赖
以依赖注入ServletRequest为例。
注册可解析依赖
// 这里表明当需要注入ServletRequest类型的时候,实际上是使用RequestObjectFactory,而RequestObjectFactory实现了ObjectFactory接口
// 该方法会将它们之间的关联关系保存到resolvableDependencies集合中
beanFactory.registerResolvableDependency(ServletRequest.class, new RequestObjectFactory());
处理可解析依赖
处理逻辑是在resolveDependency() -> doResolveDependency() -> findAutowireCandidates()方法中。
// DefaultListableBeanFactory.java
protected Map<String, Object> findAutowireCandidates(
@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
// 循环判断要注入的类型是否存在于可解析依赖的集合中
for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
Class<?> autowiringType = classObjectEntry.getKey();
// 如果需要注入的类型是注册的类型或是其子类则通过
if (autowiringType.isAssignableFrom(requiredType)) {
Object autowiringValue = classObjectEntry.getValue();
// 解析注入的对象,这里主要是为了生成代理对象,通过代理对象实现ObjectFactory对象的getObject()方法调用,最终调用到实际的Bean方法中
autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
if (requiredType.isInstance(autowiringValue)) {
result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
break;
}
}
}
// ...
return result;
}
// AutowireUtils.java
public static Object resolveAutowiringValue(Object autowiringValue, Class<?> requiredType) {
// 如果可解析依赖的value对象是ObjectFactory类型并且需要注入的类型和该value对象的实际类型不一致,则需要创建代理
if (autowiringValue instanceof ObjectFactory && !requiredType.isInstance(autowiringValue)) {
ObjectFactory<?> factory = (ObjectFactory<?>) autowiringValue;
if (autowiringValue instanceof Serializable && requiredType.isInterface()) {
// 创建代理对象,handler为ObjectFactoryDelegatingInvocationHandler,其持有ObjectFactory实现类对象
autowiringValue = Proxy.newProxyInstance(requiredType.getClassLoader(),
new Class<?>[] {requiredType}, new ObjectFactoryDelegatingInvocationHandler(factory));
}
else {
return factory.getObject();
}
}
return autowiringValue;
}
private static class ObjectFactoryDelegatingInvocationHandler implements InvocationHandler, Serializable {
private final ObjectFactory<?> objectFactory;
public ObjectFactoryDelegatingInvocationHandler(ObjectFactory<?> objectFactory) {
this.objectFactory = objectFactory;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
if (methodName.equals("equals")) {
// Only consider equal when proxies are identical.
return (proxy == args[0]);
}
else if (methodName.equals("hashCode")) {
// Use hashCode of proxy.
return System.identityHashCode(proxy);
}
else if (methodName.equals("toString")) {
return this.objectFactory.toString();
}
try {
// 通过objectFactory.getObject()获取实际对象,然后通过反射调用该对象的方法
return method.invoke(this.objectFactory.getObject(), args);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
}
private static class RequestObjectFactory implements ObjectFactory<ServletRequest>, Serializable {
@Override
public ServletRequest getObject() {
// 通过ThreadLocal获取到ServletRequest对象
return currentRequestAttributes().getRequest();
}
@Override
public String toString() {
return "Current HttpServletRequest";
}
}
使用ObjectProvider类型进行依赖注入
解决Bean不存在问题
@Component
public class Home {
private User user;
public Home(ObjectProvider<User> user) {
// 如果User Bean对象不存在,这里会返回null
this.user = user.getIfAvailable();
}
}
解决多Bean问题
@Component
public class HomeService {
private User user;
public Home(ObjectProvider<User> user) {
// 如果发现多个匹配的Bean,可以依赖需求从中手动选择一个
this.user = user.orderedStream().findFirst().orElse(null);
}
}