/* * Copyright 2010-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.data.gemfire.serialization; import org.apache.geode.DataSerializable; import org.apache.geode.Instantiator; import org.springframework.beans.BeanUtils; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.wiring.BeanConfigurerSupport; /** * Instantiator that performs instance wiring using the Spring IoC container, allowing common properties * to be injected before the object is hydrated/deserialized. The newly created instances can be configured * either by relying on an existing bean definition (which acts as a template) or by providing an embedded * configuration through annotations. * * Can reuse existing instantiators to optimize instance creation. If one is not provided, it will fallback * to reflection invocation. * * By default, on initialization, the class will register itself as an {@link Instantiator} through * {@link #register(Instantiator)}. This behaviour can be disabled through {@link #setAutoRegister(boolean)}. * Additionally, the instantiator registration is not distributed by default, to allow the application context * to be reused. This can be changed through {@link #setDistribute(boolean)}. * * @see org.springframework.beans.factory.wiring.BeanConfigurerSupport * @see org.springframework.beans.factory.wiring.BeanWiringInfoResolver * @see org.springframework.beans.factory.annotation.Autowired * @see javax.annotation.Resource * * @author Costin Leau */ public class WiringInstantiator extends Instantiator implements BeanFactoryAware, InitializingBean, DisposableBean { private final Instantiator instantiator; private final Class<? extends DataSerializable> clazz; private BeanConfigurerSupport configurer; private BeanFactory beanFactory; private boolean autoRegister = true; private boolean distribute = false; public WiringInstantiator(Instantiator instantiator) { super(instantiator.getInstantiatedClass(), instantiator.getId()); this.instantiator = instantiator; this.clazz = null; } public WiringInstantiator(Class<? extends DataSerializable> c, int classId) { super(c, classId); instantiator = null; clazz = c; } public void afterPropertiesSet() { if (configurer == null) { configurer = new BeanConfigurerSupport(); configurer.setBeanFactory(beanFactory); configurer.afterPropertiesSet(); } if (autoRegister) { Instantiator.register(this, distribute); } } public void destroy() throws Exception { configurer.destroy(); } public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } @Override public DataSerializable newInstance() { DataSerializable instance = createInstance(); configurer.configureBean(instance); return instance; } private DataSerializable createInstance() { if (instantiator != null) { return instantiator.newInstance(); } return BeanUtils.instantiate(clazz); } /** * Sets the manager responsible for configuring the newly created instances. * The given configurer needs to be configured and initialized before-hand. * * @param configurer the configurer to set */ public void setConfigurer(BeanConfigurerSupport configurer) { this.configurer = configurer; } /** * Sets the auto-registration of this {@link Instantiator} during the container startup. * Default is true, meaning the registration will occur once this factory is initialized. * * @see #register(Instantiator) * @param autoRegister the autoRegister to set */ public void setAutoRegister(boolean autoRegister) { this.autoRegister = autoRegister; } /** * Sets the distribution of the region of this {@link Instantiator} during the container startup. * Default is false, meaning the registration will not be distributed to other clients. * * @see #register(Instantiator, boolean) * @param distribute whether the registration is distributable or not */ public void setDistribute(boolean distribute) { this.distribute = distribute; } }