
infra.beans.factory.FactoryBean Maven / Gradle / Ivy
/*
* Copyright 2017 - 2024 the original author or authors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see [https://www.gnu.org/licenses/]
*/
package infra.beans.factory;
import infra.beans.factory.config.BeanDefinition;
import infra.core.AttributeAccessor;
import infra.lang.Nullable;
/**
* Interface to be implemented by objects used within a {@link BeanFactory} which
* are themselves factories for individual objects. If a bean implements this
* interface, it is used as a factory for an object to expose, not directly as a
* bean instance that will be exposed itself.
*
* NB: A bean that implements this interface cannot be used as a normal bean.
* A FactoryBean is defined in a bean style, but the object exposed for bean
* references ({@link #getObject()}) is always the object that it creates.
*
*
FactoryBeans can support singletons and prototypes, and can either create
* objects lazily on demand or eagerly on startup. The {@link SmartFactoryBean}
* interface allows for exposing more fine-grained behavioral metadata.
*
*
This interface is heavily used within the framework itself, for example for
* the AOP {@link infra.aop.framework.ProxyFactoryBean} or the
* {@link infra.jndi.JndiObjectFactoryBean}. It can be used for
* custom components as well; however, this is only common for infrastructure code.
*
*
{@code FactoryBean} is a programmatic contract. Implementations are not
* supposed to rely on annotation-driven injection or other reflective facilities.
* Invocations of {@link #getObjectType()} and {@link #getObject()} may arrive early
* in the bootstrap process, even ahead of any post-processor setup. If you need access
* to other beans, implement {@link BeanFactoryAware} and obtain them programmatically.
*
*
The container is only responsible for managing the lifecycle of the FactoryBean
* instance, not the lifecycle of the objects created by the FactoryBean. Therefore,
* a destroy method on an exposed bean object (such as {@link java.io.Closeable#close()})
* will not be called automatically. Instead, a FactoryBean should implement
* {@link DisposableBean} and delegate any such close call to the underlying object.
*
*
Finally, FactoryBean objects participate in the containing BeanFactory's
* synchronization of bean creation. Thus, there is usually no need for internal
* synchronization other than for purposes of lazy initialization within the
* FactoryBean itself (or the like).
*
* @author Rod Johnson
* @author Juergen Hoeller
* @author 海子 Yang
* @see BeanFactory
* @see infra.aop.framework.ProxyFactoryBean
* @see infra.jndi.JndiObjectFactoryBean
* @since 2018-08-03 17:38
*/
public interface FactoryBean {
/**
* The name of an attribute that can be
* {@link AttributeAccessor#setAttribute set} on a
* {@link BeanDefinition} so that
* factory beans can signal their object type when it can't be deduced from
* the factory bean class.
*
* @since 4.0
*/
String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
/**
* Return an instance (possibly shared or independent) of the object
* managed by this factory.
* As with a {@link BeanFactory}, this allows support for both the
* Singleton and Prototype design patterns.
*
If this FactoryBean is not fully initialized yet at the time of
* the call (for example because it is involved in a circular reference),
* throw a corresponding {@link FactoryBeanNotInitializedException}.
*
FactoryBeans are allowed to return {@code null} objects. The bean
* factory will consider this as a normal value to be used and will not throw
* a {@code FactoryBeanNotInitializedException} in this case. However,
* FactoryBean implementations are encouraged to throw
* {@code FactoryBeanNotInitializedException} themselves, as appropriate.
*
* @return an instance of the bean (can be {@code null})
* @throws Exception in case of creation errors
* @see FactoryBeanNotInitializedException
* @since 4.0
*/
T getObject() throws Exception;
/**
* Return the type of object that this FactoryBean creates,
* or {@code null} if not known in advance.
*
This allows one to check for specific types of beans without
* instantiating objects, for example on autowiring.
*
In the case of implementations that create a singleton object,
* this method should try to avoid singleton creation as far as possible;
* it should rather estimate the type in advance.
* For prototypes, returning a meaningful type here is advisable too.
*
This method can be called before this FactoryBean has
* been fully initialized. It must not rely on state created during
* initialization; of course, it can still use such state if available.
*
NOTE: Autowiring will simply ignore FactoryBeans that return
* {@code null} here. Therefore, it is highly recommended to implement
* this method properly, using the current state of the FactoryBean.
*
* @return the type of object that this FactoryBean creates,
* or {@code null} if not known at the time of the call
* @see BeanFactory#getBeansOfType
* @since 2.1.2
*/
@Nullable
Class> getObjectType();
/**
* Is the object managed by this factory a singleton? That is,
* will {@link #getObject()} always return the same object
* (a reference that can be cached)?
*
NOTE: If a FactoryBean indicates that it holds a singleton
* object, the object returned from {@code getObject()} might get cached
* by the owning BeanFactory. Hence, do not return {@code true}
* unless the FactoryBean always exposes the same reference.
*
The singleton status of the FactoryBean itself will generally
* be provided by the owning BeanFactory; usually, it has to be
* defined as singleton there.
*
NOTE: This method returning {@code false} does not
* necessarily indicate that returned objects are independent instances.
* An implementation of the extended {@link SmartFactoryBean} interface
* may explicitly indicate independent instances through its
* {@link SmartFactoryBean#isPrototype()} method. Plain {@link FactoryBean}
* implementations which do not implement this extended interface are
* simply assumed to always return independent instances if the
* {@code isSingleton()} implementation returns {@code false}.
*
The default implementation returns {@code true}, since a
* {@code FactoryBean} typically manages a singleton instance.
*
* @return whether the exposed object is a singleton
* @see #getObject()
* @see SmartFactoryBean#isPrototype()
*/
default boolean isSingleton() {
return true;
}
}