@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(); }
@Override public String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean includeFactoryBeans) { boolean isFactoryType = (type != null && FactoryBean.class.isAssignableFrom(type)); List<String> matches = new ArrayList<String>(); for (String name : this.beans.keySet()) { Object beanInstance = this.beans.get(name); if (beanInstance instanceof FactoryBean && !isFactoryType) { if (includeFactoryBeans) { 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 */ 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; } }
@Override public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException { String beanName = transformedBeanName(name); Object beanInstance = getSingleton(beanName, false); if (beanInstance != null) { return (beanInstance instanceof FactoryBean); } else if (containsSingleton(beanName)) { // null instance registered return false; } // No singleton instance found -> check bean definition. if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) { // No bean definition found in this factory -> delegate to parent. return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name); } return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName)); }
/** * 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; } }
@Override protected Class<?> predictBeanType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) { Class<?> targetType = mbd.getTargetType(); if (targetType == null) { targetType = (mbd.getFactoryMethodName() != null ? getTypeForFactoryMethod(beanName, mbd, typesToMatch) : resolveBeanClass(mbd, beanName, typesToMatch)); if (ObjectUtils.isEmpty(typesToMatch) || getTempClassLoader() == null) { mbd.setTargetType(targetType); } } // 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.equals(typesToMatch[0]) || FactoryBean.class.isAssignableFrom(predicted))) { return predicted; } } } } return targetType; }
/** * Obtain a "shortcut" non-singleton FactoryBean instance to use for a * {@code getObjectType()} call, without full initialization * of the FactoryBean. * @param beanName the name of the bean * @param mbd the bean definition for the bean * @return the FactoryBean instance, or {@code null} to indicate * that we couldn't obtain a shortcut FactoryBean instance */ private FactoryBean<?> getNonSingletonFactoryBeanForTypeCheck(String beanName, RootBeanDefinition mbd) { if (isPrototypeCurrentlyInCreation(beanName)) { return null; } Object instance = null; try { // Mark this bean as currently in creation, even if just partially. beforePrototypeCreation(beanName); // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. instance = resolveBeforeInstantiation(beanName, mbd); if (instance == null) { BeanWrapper bw = createBeanInstance(beanName, mbd, null); instance = bw.getWrappedInstance(); } } finally { // Finished partial creation of this bean. afterPrototypeCreation(beanName); } return getFactoryBean(beanName, instance); }
private FuzzyBoolean contextMatch(Class<?> targetType) { String advisedBeanName = getCurrentProxiedBeanName(); if (advisedBeanName == null) { // no proxy creation in progress // abstain; can't return YES, since that will make pointcut with negation fail return FuzzyBoolean.MAYBE; } if (BeanFactoryUtils.isGeneratedBeanName(advisedBeanName)) { return FuzzyBoolean.NO; } if (targetType != null) { boolean isFactory = FactoryBean.class.isAssignableFrom(targetType); return FuzzyBoolean.fromBoolean( matchesBeanName(isFactory ? BeanFactory.FACTORY_BEAN_PREFIX + advisedBeanName : advisedBeanName)); } else { return FuzzyBoolean.fromBoolean(matchesBeanName(advisedBeanName) || matchesBeanName(BeanFactory.FACTORY_BEAN_PREFIX + advisedBeanName)); } }
@Bean public FactoryBean<EntityManagerFactory> entityManagerFactory() { LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); emf.setDataSource(dataSource()); emf.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); emf.setPackagesToScan(TestJpaDomain.class.getPackage().getName()); emf.setPersistenceUnitName("test"); return emf; }
@Test public void should_resolve_factory_bean_definition() { //given final String factoryBeanName = "factoryBean"; final DoubleRegistry doubleRegistry = new DoubleRegistry( emptyList(), emptyList()); final ApplicationContext appCtx = buildAppContext(Stream.of( bean(factoryBeanName, new AnyFactoryBean()) )); final BeanDefinitionFinder definitionFinder = new BeanDefinitionFinder(appCtx, doubleRegistry); //when Optional<BeanDefinition> definition = definitionFinder.tryToFindBeanDefinition(FACTORY_BEAN_PREFIX + factoryBeanName, FactoryBean.class); //then assertTrue(definition.isPresent()); }
@Bean(MOCK) FactoryBean<Service> notMockFactoryBean() { return new FactoryBean<Service>() { @Override public Service getObject() throws Exception { return notMock; } @Override public Class<?> getObjectType() { return Service.class; } @Override public boolean isSingleton() { return true; } }; }
@Bean(SPY) FactoryBean<Service> notSpyFactoryBean() { return new FactoryBean<Service>() { @Override public Service getObject() throws Exception { return notSpy; } @Override public Class<?> getObjectType() { return Service.class; } @Override public boolean isSingleton() { return true; } }; }
@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())); }
@Test public void findsBeansByTypeIfNotInstantiated() { AnnotationConfigApplicationContext bf = new AnnotationConfigApplicationContext(); bf.registerBeanDefinition("fooConfig", new RootBeanDefinition(FooConfig.class)); bf.getBeanFactory().addBeanPostProcessor(new PredictingBPP()); bf.refresh(); 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())); }
@Test public void configWithFactoryBeanReturnType() { ListableBeanFactory factory = initBeanFactory(ConfigWithNonSpecificReturnTypes.class); assertEquals(List.class, factory.getType("factoryBean")); assertTrue(factory.isTypeMatch("factoryBean", List.class)); assertEquals(FactoryBean.class, factory.getType("&factoryBean")); assertTrue(factory.isTypeMatch("&factoryBean", FactoryBean.class)); assertFalse(factory.isTypeMatch("&factoryBean", BeanClassLoaderAware.class)); assertFalse(factory.isTypeMatch("&factoryBean", ListFactoryBean.class)); assertTrue(factory.getBean("factoryBean") instanceof List); String[] beanNames = factory.getBeanNamesForType(FactoryBean.class); assertEquals(1, beanNames.length); assertEquals("&factoryBean", beanNames[0]); beanNames = factory.getBeanNamesForType(BeanClassLoaderAware.class); assertEquals(1, beanNames.length); assertEquals("&factoryBean", beanNames[0]); beanNames = factory.getBeanNamesForType(ListFactoryBean.class); assertEquals(1, beanNames.length); assertEquals("&factoryBean", beanNames[0]); beanNames = factory.getBeanNamesForType(List.class); assertEquals("factoryBean", beanNames[0]); }
@Bean public FactoryBean testBean() { final String name = env.getProperty("testbean.name"); return new FactoryBean() { @Override public Object getObject() { return new TestBean(name); } @Override public Class<?> getObjectType() { return TestBean.class; } @Override public boolean isSingleton() { return false; } }; }
@Test public void testGetObjectTypeWithNoTargetOrTargetSource() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); new XmlBeanDefinitionReader(bf).loadBeanDefinitions(new ClassPathResource(TARGETSOURCE_CONTEXT, CLASS)); ITestBean tb = (ITestBean) bf.getBean("noTarget"); try { tb.getName(); fail(); } catch (UnsupportedOperationException ex) { assertEquals("getName", ex.getMessage()); } FactoryBean<?> pfb = (ProxyFactoryBean) bf.getBean("&noTarget"); assertTrue("Has correct object type", ITestBean.class.isAssignableFrom(pfb.getObjectType())); }
@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); }
@Test public void testAutoProxyCreatorWithFactoryBeanAndPrototype() { StaticApplicationContext sac = new StaticApplicationContext(); sac.registerSingleton("testAutoProxyCreator", TestAutoProxyCreator.class); MutablePropertyValues pvs = new MutablePropertyValues(); pvs.add("singleton", "false"); sac.registerSingleton("prototypeFactoryToBeProxied", DummyFactory.class, pvs); sac.refresh(); TestAutoProxyCreator tapc = (TestAutoProxyCreator) sac.getBean("testAutoProxyCreator"); tapc.testInterceptor.nrOfInvocations = 0; FactoryBean<?> prototypeFactory = (FactoryBean<?>) sac.getBean("&prototypeFactoryToBeProxied"); assertTrue(AopUtils.isCglibProxy(prototypeFactory)); TestBean tb = (TestBean) sac.getBean("prototypeFactoryToBeProxied"); assertTrue(AopUtils.isCglibProxy(tb)); assertEquals(2, tapc.testInterceptor.nrOfInvocations); tb.getAge(); assertEquals(3, tapc.testInterceptor.nrOfInvocations); }
@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 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) { if (ex instanceof BeanCurrentlyInCreationException) { if (logger.isDebugEnabled()) { logger.debug("Bean currently in creation on FactoryBean type check: " + ex); } } else { if (logger.isWarnEnabled()) { logger.warn("Bean creation exception on FactoryBean type check: " + ex); } } onSuppressedException(ex); return null; } }
@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; }
@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; } }; }
@ConditionalOnMissingBean(name = "httpClient") @Bean public FactoryBean<SimpleHttpClient> httpClient() { final SimpleHttpClientFactoryBean.DefaultHttpClient c = new SimpleHttpClientFactoryBean.DefaultHttpClient(); c.setConnectionTimeout(casProperties.getHttpClient().getConnectionTimeout()); c.setReadTimeout(Long.valueOf(casProperties.getHttpClient().getReadTimeout()).intValue()); return c; }
private boolean isVerticleBeanDefinition(String beanName, BeanDefinition beanDefinition) { Class<?> beanClass = getBeanClass(beanName, beanDefinition); if (beanClass != null) { if (Verticle.class.isAssignableFrom(beanClass)) { return true; } if (FactoryBean.class.isAssignableFrom(beanClass) && beanDefinition instanceof AnnotatedBeanDefinition) { MethodMetadata factoryMethodMetadata = ((AnnotatedBeanDefinition) beanDefinition).getFactoryMethodMetadata(); if (factoryMethodMetadata != null && factoryMethodMetadata.isAnnotated(VerticleDeployment.class.getName())) { return true; } } } return false; }
@Bean public FactoryBean<EntityManagerFactory> entityManagerFactory() { LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); emf.setDataSource(dataSource()); HibernateJpaVendorAdapter va = new HibernateJpaVendorAdapter(); va.setShowSql(true); emf.setJpaVendorAdapter(va); emf.setPackagesToScan(TestJpaDomain.class.getPackage().getName()); emf.setPersistenceUnitName("test"); return emf; }
@Bean public FactoryBean<EntityManagerFactory> entityManagerFactory() { LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); emf.setDataSource(dataSource()); emf.setJpaVendorAdapter(new EclipseLinkJpaVendorAdapter()); emf.setPackagesToScan(TestJpaDomain.class.getPackage().getName()); emf.setPersistenceUnitName("test"); emf.getJpaPropertyMap().put("eclipselink.weaving", "false"); return emf; }