/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library 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 Lesser General Public License for more * details. */ package com.liferay.portal.spring.bean; import com.liferay.portal.cluster.ClusterableAdvice; import com.liferay.portal.kernel.bean.BeanLocatorException; import com.liferay.portal.kernel.bean.BeanReference; import com.liferay.portal.kernel.bean.PortalBeanLocatorUtil; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.module.framework.service.IdentifiableOSGiService; import java.io.PrintWriter; import java.io.StringWriter; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.util.ReflectionUtils; /** * @author Michael Young * @author Shuyang Zhou */ public class BeanReferenceAnnotationBeanPostProcessor implements BeanFactoryAware, BeanPostProcessor { public BeanReferenceAnnotationBeanPostProcessor() { if (_log.isDebugEnabled()) { _log.debug("Creating instance " + hashCode()); } } public BeanReferenceAnnotationBeanPostProcessor(BeanFactory beanFactory) { this(); _beanFactory = beanFactory; } public void destroy() { _beans.clear(); } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (!(bean instanceof IdentifiableOSGiService) && beanName.endsWith("Service") && _log.isWarnEnabled()) { _log.warn( beanName + " should implement " + IdentifiableOSGiService.class.getName() + " for " + ClusterableAdvice.class.getName()); } _autoInject(bean, beanName, bean.getClass()); return bean; } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { _beanFactory = beanFactory; } private void _autoInject( Object targetBean, String targetBeanName, Class<?> beanClass) { if ((beanClass == null) || beanClass.isInterface()) { return; } String className = beanClass.getName(); if (className.equals(_JAVA_LANG_OBJECT) || className.startsWith(_ORG_SPRINGFRAMEWORK)) { return; } Field[] fields = beanClass.getDeclaredFields(); for (Field field : fields) { BeanReference beanReference = field.getAnnotation( BeanReference.class); String referencedBeanName = null; Class<?> referencedBeanType = null; if (beanReference != null) { referencedBeanName = beanReference.name(); referencedBeanType = beanReference.type(); } else { continue; } if (!Object.class.equals(referencedBeanType)) { referencedBeanName = referencedBeanType.getName(); } Object referencedBean = _beans.get(referencedBeanName); if (referencedBean == null) { try { referencedBean = _beanFactory.getBean(referencedBeanName); } catch (NoSuchBeanDefinitionException nsbde) { try { referencedBean = PortalBeanLocatorUtil.locate( referencedBeanName); } catch (BeanLocatorException ble) { StringWriter stringWriter = new StringWriter(); try (PrintWriter printWriter = new PrintWriter( stringWriter)) { printWriter.print( "BeanFactory could not find bean: "); nsbde.printStackTrace(printWriter); printWriter.print( " and PortalBeanLocator failed with: "); printWriter.append(ble.getMessage()); } throw new BeanLocatorException( stringWriter.toString(), ble); } } _beans.put(referencedBeanName, referencedBean); } ReflectionUtils.makeAccessible(field); BeanReferenceRefreshUtil.registerRefreshPoint( _beanFactory, targetBean, field, referencedBeanName); try { field.set(targetBean, referencedBean); } catch (Throwable t) { throw new BeanCreationException( targetBeanName, "Could not inject BeanReference fields", t); } } _autoInject(targetBean, targetBeanName, beanClass.getSuperclass()); } private static final String _JAVA_LANG_OBJECT = "java.lang.Object"; private static final String _ORG_SPRINGFRAMEWORK = "org.springframework"; private static final Log _log = LogFactoryUtil.getLog( BeanReferenceAnnotationBeanPostProcessor.class); private BeanFactory _beanFactory; private final Map<String, Object> _beans = new HashMap<>(); }