All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gate.util.spring.xml.PooledProxyBeanDefinitionDecorator Maven / Gradle / Ivy

There is a newer version: 9.0.1
Show newest version
/*
 *  PooledProxyBeanDefinitionDecorator.java
 *
 *  Copyright (c) 1995-2012, The University of Sheffield. See the file
 *  COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
 *
 *  This file is part of GATE (see http://gate.ac.uk/), and is free
 *  software, licenced under the GNU Library General Public License,
 *  Version 2, June 1991 (in the distribution as file licence.html,
 *  and also available at http://gate.ac.uk/gate/licence.html).
 *
 *  Ian Roberts, 10/Apr/2010
 *
 *  $Id: PooledProxyBeanDefinitionDecorator.java 18817 2015-07-08 10:18:34Z ian_roberts $
 */
package gate.util.spring.xml;

import javax.xml.XMLConstants;

import gate.util.GateRuntimeException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionDecorator;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.core.Conventions;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

/**
 * Bean decorator to easily create a pool of target beans.
 * 
 * 
 * <bean id="myBean" class="some.pkg.MyBean">
 *   <property name="gateApplication" ref="app" />
 *   <gate:pooled-proxy max-size="3" />
 * </bean>
 * 
* *

* This replaces the myBean bean with a proxy that * delegates to a pool of target objects. The targets are obtained by * converting the original myBean definition to a * prototype-scoped bean definition and setting that as the * targetBeanName of a CommonsPoolTargetSource. The * CommonsPoolTargetSource is then used as the target source for a * standard ProxyFactoryBean, which is created with the scope specified * in the original myBean definition (usually singleton). *

* *

* If the pooled-proxy element has an attribute proxy-target-class, this * value is passed through to the generated ProxyFactoryBean. All other * attributes are passed through to the CommonsPoolTargetSource. The * element also supports an initial-size attribute. If specified it will * pre-populate the pool with this number of instances, which is useful * if you want to load several copies of a saved application up-front * (the normal behaviour of a Spring pool is to only instantiate the * pooled objects as and when they are required). *

* *

* NOTE In addition to the spring-aop JAR, you also * need the Apache commons-pool JAR and its dependencies * available to your application in order to use this class. *

*/ public class PooledProxyBeanDefinitionDecorator implements BeanDefinitionDecorator { public static final String TARGET_PREFIX = "gate.util.spring.pool-target."; public static final String TARGET_SOURCE_PREFIX = "gate.util.spring.pool-target-source."; public static final String POOL_FILLER_PREFIX = "gate.util.spring.pool-filler."; private static final String PROXY_TARGET_CLASS = "proxy-target-class"; private static final String INITIAL_SIZE = "initial-size"; private static final String TARGET_SOURCE_CLASS = "target-source-class"; @Override public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) { String originalBeanName = definition.getBeanName(); String[] originalAliases = definition.getAliases(); String targetBeanName = TARGET_PREFIX + originalBeanName; BeanDefinition targetDefinition = definition.getBeanDefinition(); BeanDefinitionRegistry reg = parserContext.getRegistry(); // remember the scope of the original definition, // change the target bean to be prototype. String originalScope = targetDefinition.getScope(); targetDefinition.setScope("prototype"); // create a bean definition for the target source, pointing at the // target bean name RootBeanDefinition targetSourceDefinition = new RootBeanDefinition(); targetSourceDefinition.setScope(originalScope); String targetSourceClassName = null; if(node instanceof Element && ((Element)node).hasAttribute(TARGET_SOURCE_CLASS)) { targetSourceClassName = ((Element)node).getAttribute(TARGET_SOURCE_CLASS); } else { try { Class.forName("org.apache.commons.pool2.impl.GenericObjectPool"); // if we get here then commons-pool2 is available targetSourceClassName = "gate.util.spring.xml.SoftIdleCommonsPool2TargetSource"; } catch(ClassNotFoundException e) { try { Class.forName("org.apache.commons.pool.impl.GenericObjectPool"); // if we get here then commons-pool (v1) is available targetSourceClassName = "gate.util.spring.xml.SoftIdleCommonsPoolTargetSource"; } catch(ClassNotFoundException e1) { throw new GateRuntimeException("Neither commons-pool2 nor commons-pool available"); } } } targetSourceDefinition.setBeanClassName(targetSourceClassName); targetSourceDefinition.getPropertyValues().addPropertyValue( "targetBeanName", targetBeanName); String targetSourceBeanName = TARGET_SOURCE_PREFIX + originalBeanName; // apply any attributes of the pooled-proxy element except // proxy-target-class and initial-size as properties of the // target source if(node instanceof Element) { Element ele = (Element)node; NamedNodeMap attrs = ele.getAttributes(); for(int i = 0; i < attrs.getLength(); i++) { Attr att = (Attr)attrs.item(i); if(!XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(att.getNamespaceURI()) && !XMLConstants.XML_NS_URI.equals(att.getNamespaceURI()) && !XMLConstants.XMLNS_ATTRIBUTE.equals(att.getLocalName()) && !PROXY_TARGET_CLASS.equals(att.getLocalName()) && !INITIAL_SIZE.equals(att.getLocalName()) && !TARGET_SOURCE_CLASS.equals(att.getLocalName())) { String propName = Conventions.attributeNameToPropertyName(att.getLocalName()); targetSourceDefinition.getPropertyValues().addPropertyValue(propName, att.getValue()); } } } // create a bean definition for the proxy, pointing to the target // source RootBeanDefinition proxyDefinition = new RootBeanDefinition(); proxyDefinition.setScope(originalScope); proxyDefinition .setBeanClassName("org.springframework.aop.framework.ProxyFactoryBean"); proxyDefinition.getPropertyValues().addPropertyValue("targetSource", new RuntimeBeanReference(targetSourceBeanName)); Boolean proxyTargetClass = Boolean.TRUE; if(node instanceof Element) { Element ele = (Element)node; if(ele.hasAttribute(PROXY_TARGET_CLASS)) { proxyTargetClass = Boolean.valueOf(ele.getAttribute(PROXY_TARGET_CLASS)); } } proxyDefinition.getPropertyValues().addPropertyValue("proxyTargetClass", proxyTargetClass); if(targetDefinition instanceof AbstractBeanDefinition) { AbstractBeanDefinition abd = (AbstractBeanDefinition)targetDefinition; proxyDefinition.setDependsOn(abd.getDependsOn()); proxyDefinition.setAutowireCandidate(abd.isAutowireCandidate()); // The target bean should be ignored in favor of the scoped proxy. abd.setAutowireCandidate(false); } // if we have an initial-size attribute, create a pool filler bean // to pre-fill the pool to the stated initial size if(node instanceof Element && ((Element)node).hasAttribute(INITIAL_SIZE)) { RootBeanDefinition poolFillerDefinition = new RootBeanDefinition(PoolFiller.class); String poolFillerBeanName = POOL_FILLER_PREFIX + originalBeanName; poolFillerDefinition.getPropertyValues().addPropertyValue("targetSource", new RuntimeBeanReference(targetSourceBeanName)); poolFillerDefinition.getPropertyValues().addPropertyValue("numInstances", ((Element)node).getAttribute(INITIAL_SIZE)); poolFillerDefinition.setScope(targetSourceDefinition.getScope()); // make the proxy depend on the pool filler String[] proxyDepends = proxyDefinition.getDependsOn(); if(proxyDepends == null) { proxyDepends = new String[1]; } else { String[] newDepends = new String[proxyDepends.length + 1]; System.arraycopy(proxyDepends, 0, newDepends, 0, proxyDepends.length); proxyDepends = newDepends; } proxyDepends[proxyDepends.length - 1] = poolFillerBeanName; proxyDefinition.setDependsOn(proxyDepends); reg.registerBeanDefinition(poolFillerBeanName, poolFillerDefinition); } // register the (prototype) target bean under its new name reg.registerBeanDefinition(targetBeanName, targetDefinition); // register the target source reg.registerBeanDefinition(targetSourceBeanName, targetSourceDefinition); // return the bean definition for the proxy return new BeanDefinitionHolder(proxyDefinition, originalBeanName, originalAliases); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy