/* * Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com * The software in this package is published under the terms of the CPAL v1.0 * license, a copy of which has been included with this distribution in the * LICENSE.txt file. */ package org.mule.runtime.config.spring.util; import org.mule.runtime.core.api.MuleContext; import org.mule.runtime.core.api.construct.FlowConstructAware; import org.mule.runtime.api.lifecycle.InitialisationException; import org.mule.runtime.api.i18n.I18nMessageFactory; import org.mule.runtime.core.object.AbstractObjectFactory; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; /** * This is an implementation of the ObjectFactory interface which simply delegates to the Spring ApplicationContext. Since the * delegation happens each time a call to getOrCreate() is made, this will correctly handle Spring beans which are non-singletons * (factory beans, etc.) * * Singleton usage: * * <model> <service name="myOrangeService"> <service> <spring-object bean="myBean"/> </service> </service> </model> * * <spring:bean id="myBean" class="com.foo.Bar"/> * * Non-singleton usage: * * <model> <service name="myOrangeService"> <service> <spring-object bean="myFactoryBean"/> </service> </service> </model> * * <spring:bean id="myFactoryBean" class="com.foo.BarFactory" factory-method="getNewBar"/> */ public class SpringBeanLookup extends AbstractObjectFactory implements ApplicationContextAware { private ApplicationContext applicationContext; private String bean; @Override public void initialise() throws InitialisationException { if (bean == null) { throw new InitialisationException(I18nMessageFactory.createStaticMessage("Bean name has not been set."), this); } if (applicationContext == null) { throw new InitialisationException(I18nMessageFactory.createStaticMessage("ApplicationContext has not been injected."), this); } // Get instance of spring bean to determine bean type. // We do this because the result of org.springframework.beans.factory.BeanFactory.getType(String) when // used before bean initialization does not always return the same type as afterwards. One specific // case when AOP is used, and the actual bean class is returned before initialization but a proxy // afterwards. This affects both prototype beans and lazy-init singletons. objectClass = applicationContext.getBean(bean).getClass(); } @Override public void dispose() { // Not implemented for Spring Beans } @Override public Object getInstance(MuleContext muleContext) throws Exception { Object instance = applicationContext.getBean(bean); if (instance instanceof FlowConstructAware) { // The servie cannot be autowired from within Spring, so we do it here ((FlowConstructAware) instance).setFlowConstruct(flowConstruct); } fireInitialisationCallbacks(instance); return instance; } public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } public String getBean() { return bean; } public void setBean(String bean) { this.bean = bean; } @Override public boolean isSingleton() { return applicationContext.isSingleton(bean); } @Override public boolean isExternallyManagedLifecycle() { return true; } public boolean isAutoWireObject() { // Spring does the wiring return false; } }