/*
 * Copyright 2002-2018 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.aop.target;

import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamException;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;

Base class for dynamic TargetSource implementations that create new prototype bean instances to support a pooling or new-instance-per-invocation strategy.

Such TargetSources must run in a BeanFactory, as it needs to call the getBean method to create a new prototype instance. Therefore, this base class extends AbstractBeanFactoryBasedTargetSource.

Author:Rod Johnson, Juergen Hoeller
See Also:
/** * Base class for dynamic {@link org.springframework.aop.TargetSource} implementations * that create new prototype bean instances to support a pooling or * new-instance-per-invocation strategy. * * <p>Such TargetSources must run in a {@link BeanFactory}, as it needs to * call the {@code getBean} method to create a new prototype instance. * Therefore, this base class extends {@link AbstractBeanFactoryBasedTargetSource}. * * @author Rod Johnson * @author Juergen Hoeller * @see org.springframework.beans.factory.BeanFactory#getBean * @see PrototypeTargetSource * @see ThreadLocalTargetSource * @see CommonsPool2TargetSource */
@SuppressWarnings("serial") public abstract class AbstractPrototypeBasedTargetSource extends AbstractBeanFactoryBasedTargetSource { @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { super.setBeanFactory(beanFactory); // Check whether the target bean is defined as prototype. if (!beanFactory.isPrototype(getTargetBeanName())) { throw new BeanDefinitionStoreException( "Cannot use prototype-based TargetSource against non-prototype bean with name '" + getTargetBeanName() + "': instances would not be independent"); } }
Subclasses should call this method to create a new prototype instance.
Throws:
  • BeansException – if bean creation failed
/** * Subclasses should call this method to create a new prototype instance. * @throws BeansException if bean creation failed */
protected Object newPrototypeInstance() throws BeansException { if (logger.isDebugEnabled()) { logger.debug("Creating new instance of bean '" + getTargetBeanName() + "'"); } return getBeanFactory().getBean(getTargetBeanName()); }
Subclasses should call this method to destroy an obsolete prototype instance.
Params:
  • target – the bean instance to destroy
/** * Subclasses should call this method to destroy an obsolete prototype instance. * @param target the bean instance to destroy */
protected void destroyPrototypeInstance(Object target) { if (logger.isDebugEnabled()) { logger.debug("Destroying instance of bean '" + getTargetBeanName() + "'"); } if (getBeanFactory() instanceof ConfigurableBeanFactory) { ((ConfigurableBeanFactory) getBeanFactory()).destroyBean(getTargetBeanName(), target); } else if (target instanceof DisposableBean) { try { ((DisposableBean) target).destroy(); } catch (Throwable ex) { logger.warn("Destroy method on bean with name '" + getTargetBeanName() + "' threw an exception", ex); } } } //--------------------------------------------------------------------- // Serialization support //--------------------------------------------------------------------- private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { throw new NotSerializableException("A prototype-based TargetSource itself is not deserializable - " + "just a disconnected SingletonTargetSource or EmptyTargetSource is"); }
Replaces this object with a SingletonTargetSource on serialization. Protected as otherwise it won't be invoked for subclasses. (The writeReplace() method must be visible to the class being serialized.)

With this implementation of this method, there is no need to mark non-serializable fields in this class or subclasses as transient.

/** * Replaces this object with a SingletonTargetSource on serialization. * Protected as otherwise it won't be invoked for subclasses. * (The {@code writeReplace()} method must be visible to the class * being serialized.) * <p>With this implementation of this method, there is no need to mark * non-serializable fields in this class or subclasses as transient. */
protected Object writeReplace() throws ObjectStreamException { if (logger.isDebugEnabled()) { logger.debug("Disconnecting TargetSource [" + this + "]"); } try { // Create disconnected SingletonTargetSource/EmptyTargetSource. Object target = getTarget(); return (target != null ? new SingletonTargetSource(target) : EmptyTargetSource.forClass(getTargetClass())); } catch (Exception ex) { String msg = "Cannot get target for disconnecting TargetSource [" + this + "]"; logger.error(msg, ex); throw new NotSerializableException(msg + ": " + ex); } } }