下面列出了怎么用org.springframework.beans.factory.FactoryBean的API类实例代码及写法,或者点击链接到github查看源代码。
/**
* Obtain an object to expose from the given FactoryBean.
* @param factory the FactoryBean instance
* @param beanName the name of the bean
* @param shouldPostProcess whether the bean is subject for post-processing
* @return the object obtained from the FactoryBean
* @throws BeanCreationException if FactoryBean object creation failed
* @see org.springframework.beans.factory.FactoryBean#getObject()
*/
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
object = doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
}
return (object != NULL_OBJECT ? object : null);
}
}
else {
return doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
}
}
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String name, @Nullable TargetSource customTargetSource) {
if (StaticMessageSource.class.equals(beanClass)) {
return DO_NOT_PROXY;
}
else if (name.endsWith("ToBeProxied")) {
boolean isFactoryBean = FactoryBean.class.isAssignableFrom(beanClass);
if ((this.proxyFactoryBean && isFactoryBean) || (this.proxyObject && !isFactoryBean)) {
return new Object[] {this.testInterceptor};
}
else {
return DO_NOT_PROXY;
}
}
else {
return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
}
}
protected boolean isFactoryBeanMetadataMethod(Method method) {
Class<?> clazz = method.getDeclaringClass();
// Call from interface-based proxy handle, allowing for an efficient check?
if (clazz.isInterface()) {
return ((clazz == FactoryBean.class || clazz == SmartFactoryBean.class) &&
!method.getName().equals("getObject"));
}
// Call from CGLIB proxy handle, potentially implementing a FactoryBean method?
Class<?> factoryBeanType = null;
if (SmartFactoryBean.class.isAssignableFrom(clazz)) {
factoryBeanType = SmartFactoryBean.class;
} else if (FactoryBean.class.isAssignableFrom(clazz)) {
factoryBeanType = FactoryBean.class;
}
return (factoryBeanType != null && !method.getName().equals("getObject") &&
ClassUtils.hasMethod(factoryBeanType, method.getName(), method.getParameterTypes()));
}
@Override
public Class<?> getType(String name) throws NoSuchBeanDefinitionException {
String beanName = BeanFactoryUtils.transformedBeanName(name);
Object bean = this.beans.get(beanName);
if (bean == null) {
throw new NoSuchBeanDefinitionException(beanName,
"Defined beans are [" + StringUtils.collectionToCommaDelimitedString(this.beans.keySet()) + "]");
}
if (bean instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
// If it's a FactoryBean, we want to look at what it creates, not the factory class.
return ((FactoryBean<?>) bean).getObjectType();
}
return bean.getClass();
}
@Test
public void repro() {
AnnotationConfigApplicationContext bf = new AnnotationConfigApplicationContext();
bf.registerBeanDefinition("fooConfig", new RootBeanDefinition(FooConfig.class));
bf.getBeanFactory().addBeanPostProcessor(new PredictingBPP());
bf.refresh();
assertThat(bf.getBean("foo"), instanceOf(Foo.class));
assertThat(bf.getBean("&foo"), instanceOf(FooFactoryBean.class));
assertThat(bf.isTypeMatch("&foo", FactoryBean.class), is(true));
@SuppressWarnings("rawtypes")
Map<String, FactoryBean> fbBeans = bf.getBeansOfType(FactoryBean.class);
assertThat(1, equalTo(fbBeans.size()));
assertThat("&foo", equalTo(fbBeans.keySet().iterator().next()));
Map<String, AnInterface> aiBeans = bf.getBeansOfType(AnInterface.class);
assertThat(1, equalTo(aiBeans.size()));
assertThat("&foo", equalTo(aiBeans.keySet().iterator().next()));
}
@Bean
public FactoryBean<Tenant> tenantFactoryBean() {
return new FactoryBean<Tenant>() {
@Override
public Tenant getObject() throws Exception {
return Tenant.builder()
.id("tenant_id")
.domainName("domainName")
.name("Konker").build();
}
@Override
public Class<?> getObjectType() {
return Tenant.class;
}
@Override
public boolean isSingleton() {
return false;
}
};
}
/**
* Determine the type for the given FactoryBean.
* @param factoryBean the FactoryBean instance to check
* @return the FactoryBean's object type,
* or {@code null} if the type cannot be determined yet
*/
protected Class<?> getTypeForFactoryBean(final FactoryBean<?> factoryBean) {
try {
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
@Override
public Class<?> run() {
return factoryBean.getObjectType();
}
}, getAccessControlContext());
}
else {
return factoryBean.getObjectType();
}
}
catch (Throwable ex) {
// Thrown from the FactoryBean's getObjectType implementation.
logger.warn("FactoryBean threw exception from getObjectType, despite the contract saying " +
"that it should return null if the type of its object cannot be determined yet", ex);
return null;
}
}
@Test
public void testAutoProxyCreatorWithFactoryBean() {
StaticApplicationContext sac = new StaticApplicationContext();
sac.registerSingleton("testAutoProxyCreator", TestAutoProxyCreator.class);
sac.registerSingleton("singletonFactoryToBeProxied", DummyFactory.class);
sac.refresh();
TestAutoProxyCreator tapc = (TestAutoProxyCreator) sac.getBean("testAutoProxyCreator");
tapc.testInterceptor.nrOfInvocations = 0;
FactoryBean<?> factory = (FactoryBean<?>) sac.getBean("&singletonFactoryToBeProxied");
assertTrue(AopUtils.isCglibProxy(factory));
TestBean tb = (TestBean) sac.getBean("singletonFactoryToBeProxied");
assertTrue(AopUtils.isCglibProxy(tb));
assertEquals(2, tapc.testInterceptor.nrOfInvocations);
tb.getAge();
assertEquals(3, tapc.testInterceptor.nrOfInvocations);
}
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String name, @Nullable TargetSource customTargetSource) {
if (StaticMessageSource.class.equals(beanClass)) {
return DO_NOT_PROXY;
}
else if (name.endsWith("ToBeProxied")) {
boolean isFactoryBean = FactoryBean.class.isAssignableFrom(beanClass);
if ((this.proxyFactoryBean && isFactoryBean) || (this.proxyObject && !isFactoryBean)) {
return new Object[] {this.testInterceptor};
}
else {
return DO_NOT_PROXY;
}
}
else {
return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
}
}
@Override
public String[] getBeanNamesForType(ResolvableType type) {
boolean isFactoryType = (type != null && FactoryBean.class.isAssignableFrom(type.getRawClass()));
List<String> matches = new ArrayList<String>();
for (Map.Entry<String, Object> entry : this.beans.entrySet()) {
String name = entry.getKey();
Object beanInstance = entry.getValue();
if (beanInstance instanceof FactoryBean && !isFactoryType) {
Class<?> objectType = ((FactoryBean<?>) beanInstance).getObjectType();
if (objectType != null && (type == null || type.isAssignableFrom(objectType))) {
matches.add(name);
}
}
else {
if (type == null || type.isInstance(beanInstance)) {
matches.add(name);
}
}
}
return StringUtils.toStringArray(matches);
}
/**
* Determine the type for the given FactoryBean.
* @param factoryBean the FactoryBean instance to check
* @return the FactoryBean's object type,
* or {@code null} if the type cannot be determined yet
*/
@Nullable
protected Class<?> getTypeForFactoryBean(final FactoryBean<?> factoryBean) {
try {
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedAction<Class<?>>)
factoryBean::getObjectType, getAccessControlContext());
}
else {
return factoryBean.getObjectType();
}
}
catch (Throwable ex) {
// Thrown from the FactoryBean's getObjectType implementation.
logger.info("FactoryBean threw exception from getObjectType, despite the contract saying " +
"that it should return null if the type of its object cannot be determined yet", ex);
return null;
}
}
protected String getClassName(Object bean, BeanDefinition beanDefinition){
String className = null;
if(bean instanceof FactoryBean){
className = ((FactoryBean)bean).getObjectType().getName();
}else if(beanDefinition instanceof AnnotatedBeanDefinition){
MethodMetadata methodMetadata = ((AnnotatedBeanDefinition)beanDefinition).getFactoryMethodMetadata();
if(methodMetadata != null){
className = methodMetadata.getReturnTypeName();
}else{
className = ((AnnotatedBeanDefinition)beanDefinition).getMetadata().getClassName();
}
}else if(beanDefinition instanceof RootBeanDefinition){
className = bean.getClass().getName();
}else if(bean instanceof Proxy){
className = getClassNameFromProxy(bean);
}else{
className = beanDefinition.getBeanClassName();
}
return className;
}
@Bean
public FactoryBean<Tenant> tenantFactoryBean() {
return new FactoryBean<Tenant>() {
@Override
public Tenant getObject() throws Exception {
return Tenant.builder()
.id("tenant_id")
.domainName("domainName")
.name("Konker").build();
}
@Override
public Class<?> getObjectType() {
return Tenant.class;
}
@Override
public boolean isSingleton() {
return false;
}
};
}
/**
* Determine the type for the given FactoryBean.
* @param factoryBean the FactoryBean instance to check
* @return the FactoryBean's object type,
* or {@code null} if the type cannot be determined yet
*/
protected Class<?> getTypeForFactoryBean(final FactoryBean<?> factoryBean) {
try {
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
@Override
public Class<?> run() {
return factoryBean.getObjectType();
}
}, getAccessControlContext());
}
else {
return factoryBean.getObjectType();
}
}
catch (Throwable ex) {
// Thrown from the FactoryBean's getObjectType implementation.
logger.warn("FactoryBean threw exception from getObjectType, despite the contract saying " +
"that it should return null if the type of its object cannot be determined yet", ex);
return null;
}
}
/**
* Determine the bean type for the given FactoryBean definition, as far as possible.
* Only called if there is no singleton instance registered for the target bean already.
* <p>The default implementation creates the FactoryBean via {@code getBean}
* to call its {@code getObjectType} method. Subclasses are encouraged to optimize
* this, typically by just instantiating the FactoryBean but not populating it yet,
* trying whether its {@code getObjectType} method already returns a type.
* If no type found, a full FactoryBean creation as performed by this implementation
* should be used as fallback.
* @param beanName the name of the bean
* @param mbd the merged bean definition for the bean
* @return the type for the bean if determinable, or {@code null} else
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
* @see #getBean(String)
*/
protected Class<?> getTypeForFactoryBean(String beanName, RootBeanDefinition mbd) {
if (!mbd.isSingleton()) {
return null;
}
try {
FactoryBean<?> factoryBean = doGetBean(FACTORY_BEAN_PREFIX + beanName, FactoryBean.class, null, true);
return getTypeForFactoryBean(factoryBean);
}
catch (BeanCreationException ex) {
// Can only happen when getting a FactoryBean.
if (logger.isDebugEnabled()) {
logger.debug("Ignoring bean creation exception on FactoryBean type check: " + ex);
}
onSuppressedException(ex);
return null;
}
}
public SimpleTaskRepository(FactoryBean<TaskExecutionDao> taskExecutionDaoFactoryBean,
Integer maxExitMessageSize, Integer maxTaskNameSize,
Integer maxErrorMessageSize) {
Assert.notNull(taskExecutionDaoFactoryBean,
"A FactoryBean that provides a TaskExecutionDao is required");
if (maxTaskNameSize != null) {
this.maxTaskNameSize = maxTaskNameSize;
}
if (maxExitMessageSize != null) {
this.maxExitMessageSize = maxExitMessageSize;
}
if (maxErrorMessageSize != null) {
this.maxErrorMessageSize = maxErrorMessageSize;
}
this.taskExecutionDaoFactoryBean = taskExecutionDaoFactoryBean;
}
@Bean
public FactoryBean<Tenant> tenantFactoryBean() {
return new FactoryBean<Tenant>() {
@Override
public Tenant getObject() throws Exception {
return Tenant.builder()
.id("tenant_id")
.domainName("domainName")
.name("Konker").build();
}
@Override
public Class<?> getObjectType() {
return Tenant.class;
}
@Override
public boolean isSingleton() {
return false;
}
};
}
@Bean
public FactoryBean<Tenant> tenantFactoryBean() {
return new FactoryBean<Tenant>() {
@Override
public Tenant getObject() {
return Tenant.builder()
.id("tenant_id")
.domainName("domainName")
.name("Konker").build();
}
@Override
public Class<?> getObjectType() {
return Tenant.class;
}
@Override
public boolean isSingleton() {
return false;
}
};
}
@Override
protected Class<?> predictBeanType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
Class<?> targetType = determineTargetType(beanName, mbd, typesToMatch);
// Apply SmartInstantiationAwareBeanPostProcessors to predict the
// eventual type after a before-instantiation shortcut.
if (targetType != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
Class<?> predicted = ibp.predictBeanType(targetType, beanName);
if (predicted != null && (typesToMatch.length != 1 || FactoryBean.class != typesToMatch[0] ||
FactoryBean.class.isAssignableFrom(predicted))) {
return predicted;
}
}
}
}
return targetType;
}
/**
* Identify as bean to proxy if the bean name is in the configured list of names.
*/
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
if (this.beanNames != null) {
for (String mappedName : this.beanNames) {
if (FactoryBean.class.isAssignableFrom(beanClass)) {
if (!mappedName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
continue;
}
mappedName = mappedName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
if (isMatch(beanName, mappedName)) {
return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
}
BeanFactory beanFactory = getBeanFactory();
if (beanFactory != null) {
String[] aliases = beanFactory.getAliases(beanName);
for (String alias : aliases) {
if (isMatch(alias, mappedName)) {
return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
}
}
}
}
}
return DO_NOT_PROXY;
}
/**
* Get a FactoryBean for the given bean if possible.
* @param beanName the name of the bean
* @param beanInstance the corresponding bean instance
* @return the bean instance as FactoryBean
* @throws BeansException if the given bean cannot be exposed as a FactoryBean
*/
protected FactoryBean<?> getFactoryBean(String beanName, Object beanInstance) throws BeansException {
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanCreationException(beanName,
"Bean instance of type [" + beanInstance.getClass() + "] is not a FactoryBean");
}
return (FactoryBean<?>) beanInstance;
}
public MockServiceModel getMonitorMockByTarget(Object bean){
return monitorList.stream().filter(p->{
Class targetCls = bean.getClass();
if(bean instanceof FactoryBean){
targetCls = ((FactoryBean)bean).getObjectType();
}
if(p.getInterfaceCls().isAssignableFrom(targetCls)){
return true;
}
return false;
}).findFirst().orElse(null);
}
@Test
public void testRefreshableFactoryBean() {
ApplicationContext context = new ClassPathXmlApplicationContext("groovyContext.xml", getClass());
Object factory = context.getBean("&refreshableFactory");
assertTrue(factory instanceof FactoryBean);
Object result = context.getBean("refreshableFactory");
assertTrue(result instanceof String);
assertEquals("test", result);
}
@Bean
public FactoryBean<Foo> foo() {
return new FactoryBean<Foo>() {
@Override
public Foo getObject() {
return new Foo("x");
}
@Override
public Class<?> getObjectType() {
return Foo.class;
}
};
}
@Override
@SuppressWarnings("unchecked")
public <T> Map<String, T> getBeansOfType(Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
throws BeansException {
boolean isFactoryType = (type != null && FactoryBean.class.isAssignableFrom(type));
Map<String, T> matches = new HashMap<String, T>();
for (Map.Entry<String, Object> entry : this.beans.entrySet()) {
String beanName = entry.getKey();
Object beanInstance = entry.getValue();
// Is bean a FactoryBean?
if (beanInstance instanceof FactoryBean && !isFactoryType) {
// Match object created by FactoryBean.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
Class<?> objectType = factory.getObjectType();
if ((includeNonSingletons || factory.isSingleton()) &&
objectType != null && (type == null || type.isAssignableFrom(objectType))) {
matches.put(beanName, getBean(beanName, type));
}
}
else {
if (type == null || type.isInstance(beanInstance)) {
// If type to match is FactoryBean, return FactoryBean itself.
// Else, return bean instance.
if (isFactoryType) {
beanName = FACTORY_BEAN_PREFIX + beanName;
}
matches.put(beanName, (T) beanInstance);
}
}
}
return matches;
}
@Test
public void testFactoryBean() {
ApplicationContext context = new ClassPathXmlApplicationContext("groovyContext.xml", getClass());
Object factory = context.getBean("&factory");
assertTrue(factory instanceof FactoryBean);
Object result = context.getBean("factory");
assertTrue(result instanceof String);
assertEquals("test", result);
}
@Test
public void individualBeanWithFactoryBeanSupplierAndTargetType() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
RootBeanDefinition bd = new RootBeanDefinition();
bd.setInstanceSupplier(TypedFactoryBean::new);
bd.setTargetType(ResolvableType.forClassWithGenerics(FactoryBean.class, String.class));
bd.setLazyInit(true);
context.registerBeanDefinition("fb", bd);
context.refresh();
assertEquals(String.class, context.getType("fb"));
assertEquals(FactoryBean.class, context.getType("&fb"));
}
@Test
public void testAutoProxyCreatorWithFactoryBeanAndProxyObjectOnly() {
StaticApplicationContext sac = new StaticApplicationContext();
MutablePropertyValues pvs = new MutablePropertyValues();
pvs.add("proxyFactoryBean", "false");
sac.registerSingleton("testAutoProxyCreator", TestAutoProxyCreator.class, pvs);
sac.registerSingleton("singletonFactoryToBeProxied", DummyFactory.class);
sac.refresh();
TestAutoProxyCreator tapc = (TestAutoProxyCreator) sac.getBean("testAutoProxyCreator");
tapc.testInterceptor.nrOfInvocations = 0;
FactoryBean<?> factory = (FactoryBean<?>) sac.getBean("&singletonFactoryToBeProxied");
assertFalse(AopUtils.isAopProxy(factory));
TestBean tb = (TestBean) sac.getBean("singletonFactoryToBeProxied");
assertTrue(AopUtils.isCglibProxy(tb));
assertEquals(0, tapc.testInterceptor.nrOfInvocations);
tb.getAge();
assertEquals(1, tapc.testInterceptor.nrOfInvocations);
TestBean tb2 = (TestBean) sac.getBean("singletonFactoryToBeProxied");
assertSame(tb, tb2);
assertEquals(1, tapc.testInterceptor.nrOfInvocations);
tb2.getAge();
assertEquals(2, tapc.testInterceptor.nrOfInvocations);
}
@Bean
public FactoryBean<Foo> foo() {
return new FactoryBean<Foo>() {
@Override
public Foo getObject() throws Exception {
return new Foo();
}
@Override
public Class<?> getObjectType() {
return Foo.class;
}
};
}
/**
* Introspect the factory method signatures on the given bean class,
* trying to find a common {@code FactoryBean} object type declared there.
* @param beanClass the bean class to find the factory method on
* @param factoryMethodName the name of the factory method
* @return the common {@code FactoryBean} object type, or {@code null} if none
*/
private Class<?> getTypeForFactoryBeanFromMethod(Class<?> beanClass, final String factoryMethodName) {
class Holder { Class<?> value = null; }
final Holder objectType = new Holder();
// CGLIB subclass methods hide generic parameters; look at the original user class.
Class<?> fbClass = ClassUtils.getUserClass(beanClass);
// Find the given factory method, taking into account that in the case of
// @Bean methods, there may be parameters present.
ReflectionUtils.doWithMethods(fbClass,
new ReflectionUtils.MethodCallback() {
@Override
public void doWith(Method method) {
if (method.getName().equals(factoryMethodName) &&
FactoryBean.class.isAssignableFrom(method.getReturnType())) {
Class<?> currentType = GenericTypeResolver.resolveReturnTypeArgument(
method, FactoryBean.class);
if (currentType != null) {
objectType.value = ClassUtils.determineCommonAncestor(currentType, objectType.value);
}
}
}
});
return (objectType.value != null && Object.class != objectType.value ? objectType.value : null);
}