Java tutorial
/* * Copyright 2012 The Solmix Project * * This 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 software 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. * * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.gnu.org/licenses/ * or see the FSF site: http://www.fsf.org. */ package org.solmix.runtime.support.spring; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.solmix.runtime.Container; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.ConstructorArgumentValues; import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.ApplicationContext; import org.springframework.context.ConfigurableApplicationContext; /** * * @author solmix.f@gmail.com * @version $Id$ 2013-11-4 */ public class ContainerPostProcessor implements BeanFactoryPostProcessor { private Container container; String name; public ContainerPostProcessor() { } public ContainerPostProcessor(Container container) { this.container = container; } public ContainerPostProcessor(String name) { this.name = name; } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { Object inject = container; if (inject == null) { inject = getContainerByName(Container.DEFAULT_CONTAINER_ID, beanFactory, true, null); } else { if (!beanFactory.containsBeanDefinition(Container.DEFAULT_CONTAINER_ID) && !beanFactory.containsSingleton(Container.DEFAULT_CONTAINER_ID)) { beanFactory.registerSingleton(Container.DEFAULT_CONTAINER_ID, container); } } for (String beanName : beanFactory.getBeanDefinitionNames()) { BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName); Object p = beanDefinition.getAttribute(AbstractBeanDefinitionParser.WIRE_CONTAINER_ATTRIBUTE); if (p == null) continue; String name = (String) beanDefinition.getAttribute(AbstractBeanDefinitionParser.WIRE_CONTAINER_NAME); String create = (String) beanDefinition .getAttribute(AbstractBeanDefinitionParser.WIRE_CONTAINER_CREATE); Object inj = inject; if (name != null) { if (container != null) { continue; } inj = getContainerByName(name, beanFactory, create != null, create); } beanDefinition.removeAttribute(AbstractBeanDefinitionParser.WIRE_CONTAINER_NAME); beanDefinition.removeAttribute(AbstractBeanDefinitionParser.WIRE_CONTAINER_ATTRIBUTE); beanDefinition.removeAttribute(AbstractBeanDefinitionParser.WIRE_CONTAINER_CREATE); if (create == null) { if (Boolean.valueOf(p.toString())) { beanDefinition.getPropertyValues().addPropertyValue("container", inj); } else { ConstructorArgumentValues constructorArgs = beanDefinition.getConstructorArgumentValues(); insertConstructorArg(constructorArgs, inj); } } } //end loop bean. } private void insertConstructorArg(ConstructorArgumentValues constructorArgs, Object valueToInsert) { List<ValueHolder> genericArgs = new ArrayList<ValueHolder>((constructorArgs.getGenericArgumentValues())); Map<Integer, ValueHolder> indexedArgs = new HashMap<Integer, ValueHolder>( constructorArgs.getIndexedArgumentValues()); constructorArgs.clear(); for (ValueHolder genericValue : genericArgs) { constructorArgs.addGenericArgumentValue(genericValue); } for (Map.Entry<Integer, ValueHolder> entry : indexedArgs.entrySet()) { constructorArgs.addIndexedArgumentValue(entry.getKey() + 1, entry.getValue()); } constructorArgs.addIndexedArgumentValue(0, valueToInsert); } private Object getContainerByName(String name, ConfigurableListableBeanFactory factory, boolean create, String cn) { if (!factory.containsBeanDefinition(name) && (create || Container.DEFAULT_CONTAINER_ID.equals(name))) { // DefaultListableBeanFactory df = (DefaultListableBeanFactory) factory; RootBeanDefinition rbd = new RootBeanDefinition(SpringContainer.class); if (cn != null) { // SpringContainer.setConfig rbd.setAttribute("config", new RuntimeBeanReference(cn)); } df.registerBeanDefinition(name, rbd); } else if (cn != null) { BeanDefinition bd = factory.getBeanDefinition(name); bd.getPropertyValues().addPropertyValue("config", new RuntimeBeanReference(cn)); } return new RuntimeBeanReference(name); } private static Container getContainerByName(String name, ApplicationContext context, boolean create) { if (!context.containsBean(name) && (create || Container.DEFAULT_CONTAINER_ID.equals(name))) { SpringContainer b = new SpringContainer(); ConfigurableApplicationContext cctx = (ConfigurableApplicationContext) context; cctx.getBeanFactory().registerSingleton(name, b); b.setApplicationContext(context); } return context.getBean(name, Container.class); } /**Container,container?*/ public static Container addDefault(ApplicationContext ctx) { if (!ctx.containsBean(Container.DEFAULT_CONTAINER_ID)) { Container b = getContainerByName(Container.DEFAULT_CONTAINER_ID, ctx, true); if (ctx instanceof ConfigurableApplicationContext) { ConfigurableApplicationContext cctx = (ConfigurableApplicationContext) ctx; new ContainerPostProcessor(b).postProcessBeanFactory(cctx.getBeanFactory()); } } return Container.class.cast(ctx.getBean(Container.DEFAULT_CONTAINER_ID, Container.class)); } /**??container*/ public static Container addContainer(ApplicationContext ctx, String name) { return getContainerByName(name, ctx, true); } }