001/* 002 * Copyright 2002-2012 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.aop.target; 018 019import org.springframework.beans.BeansException; 020 021/** 022 * {@link org.springframework.aop.TargetSource} that lazily accesses a 023 * singleton bean from a {@link org.springframework.beans.factory.BeanFactory}. 024 * 025 * <p>Useful when a proxy reference is needed on initialization but 026 * the actual target object should not be initialized until first use. 027 * When the target bean is defined in an 028 * {@link org.springframework.context.ApplicationContext} (or a 029 * {@code BeanFactory} that is eagerly pre-instantiating singleton beans) 030 * it must be marked as "lazy-init" too, else it will be instantiated by said 031 * {@code ApplicationContext} (or {@code BeanFactory}) on startup. 032 * <p>For example: 033 * 034 * <pre class="code"> 035 * <bean id="serviceTarget" class="example.MyService" lazy-init="true"> 036 * ... 037 * </bean> 038 * 039 * <bean id="service" class="org.springframework.aop.framework.ProxyFactoryBean"> 040 * <property name="targetSource"> 041 * <bean class="org.springframework.aop.target.LazyInitTargetSource"> 042 * <property name="targetBeanName"><idref local="serviceTarget"/></property> 043 * </bean> 044 * </property> 045 * </bean></pre> 046 * 047 * The "serviceTarget" bean will not get initialized until a method on the 048 * "service" proxy gets invoked. 049 * 050 * <p>Subclasses can extend this class and override the {@link #postProcessTargetObject(Object)} to 051 * perform some additional processing with the target object when it is first loaded. 052 * 053 * @author Juergen Hoeller 054 * @author Rob Harrop 055 * @since 1.1.4 056 * @see org.springframework.beans.factory.BeanFactory#getBean 057 * @see #postProcessTargetObject 058 */ 059@SuppressWarnings("serial") 060public class LazyInitTargetSource extends AbstractBeanFactoryBasedTargetSource { 061 062 private Object target; 063 064 065 @Override 066 public synchronized Object getTarget() throws BeansException { 067 if (this.target == null) { 068 this.target = getBeanFactory().getBean(getTargetBeanName()); 069 postProcessTargetObject(this.target); 070 } 071 return this.target; 072 } 073 074 /** 075 * Subclasses may override this method to perform additional processing on 076 * the target object when it is first loaded. 077 * @param targetObject the target object that has just been instantiated (and configured) 078 */ 079 protected void postProcessTargetObject(Object targetObject) { 080 } 081 082}