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; 020import org.springframework.lang.Nullable; 021 022/** 023 * {@link org.springframework.aop.TargetSource} that lazily accesses a 024 * singleton bean from a {@link org.springframework.beans.factory.BeanFactory}. 025 * 026 * <p>Useful when a proxy reference is needed on initialization but 027 * the actual target object should not be initialized until first use. 028 * When the target bean is defined in an 029 * {@link org.springframework.context.ApplicationContext} (or a 030 * {@code BeanFactory} that is eagerly pre-instantiating singleton beans) 031 * it must be marked as "lazy-init" too, else it will be instantiated by said 032 * {@code ApplicationContext} (or {@code BeanFactory}) on startup. 033 * <p>For example: 034 * 035 * <pre class="code"> 036 * <bean id="serviceTarget" class="example.MyService" lazy-init="true"> 037 * ... 038 * </bean> 039 * 040 * <bean id="service" class="org.springframework.aop.framework.ProxyFactoryBean"> 041 * <property name="targetSource"> 042 * <bean class="org.springframework.aop.target.LazyInitTargetSource"> 043 * <property name="targetBeanName"><idref local="serviceTarget"/></property> 044 * </bean> 045 * </property> 046 * </bean></pre> 047 * 048 * The "serviceTarget" bean will not get initialized until a method on the 049 * "service" proxy gets invoked. 050 * 051 * <p>Subclasses can extend this class and override the {@link #postProcessTargetObject(Object)} to 052 * perform some additional processing with the target object when it is first loaded. 053 * 054 * @author Juergen Hoeller 055 * @author Rob Harrop 056 * @since 1.1.4 057 * @see org.springframework.beans.factory.BeanFactory#getBean 058 * @see #postProcessTargetObject 059 */ 060@SuppressWarnings("serial") 061public class LazyInitTargetSource extends AbstractBeanFactoryBasedTargetSource { 062 063 @Nullable 064 private Object target; 065 066 067 @Override 068 @Nullable 069 public synchronized Object getTarget() throws BeansException { 070 if (this.target == null) { 071 this.target = getBeanFactory().getBean(getTargetBeanName()); 072 postProcessTargetObject(this.target); 073 } 074 return this.target; 075 } 076 077 /** 078 * Subclasses may override this method to perform additional processing on 079 * the target object when it is first loaded. 080 * @param targetObject the target object that has just been instantiated (and configured) 081 */ 082 protected void postProcessTargetObject(Object targetObject) { 083 } 084 085}