001/* 002 * Copyright 2002-2018 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 java.io.Serializable; 020 021import org.springframework.aop.TargetSource; 022import org.springframework.util.Assert; 023 024/** 025 * {@link org.springframework.aop.TargetSource} implementation that 026 * caches a local target object, but allows the target to be swapped 027 * while the application is running. 028 * 029 * <p>If configuring an object of this class in a Spring IoC container, 030 * use constructor injection. 031 * 032 * <p>This TargetSource is serializable if the target is at the time 033 * of serialization. 034 * 035 * @author Rod Johnson 036 * @author Juergen Hoeller 037 */ 038public class HotSwappableTargetSource implements TargetSource, Serializable { 039 040 /** use serialVersionUID from Spring 1.2 for interoperability. */ 041 private static final long serialVersionUID = 7497929212653839187L; 042 043 044 /** The current target object. */ 045 private Object target; 046 047 048 /** 049 * Create a new HotSwappableTargetSource with the given initial target object. 050 * @param initialTarget the initial target object 051 */ 052 public HotSwappableTargetSource(Object initialTarget) { 053 Assert.notNull(initialTarget, "Target object must not be null"); 054 this.target = initialTarget; 055 } 056 057 058 /** 059 * Return the type of the current target object. 060 * <p>The returned type should usually be constant across all target objects. 061 */ 062 @Override 063 public synchronized Class<?> getTargetClass() { 064 return this.target.getClass(); 065 } 066 067 @Override 068 public final boolean isStatic() { 069 return false; 070 } 071 072 @Override 073 public synchronized Object getTarget() { 074 return this.target; 075 } 076 077 @Override 078 public void releaseTarget(Object target) { 079 // nothing to do 080 } 081 082 083 /** 084 * Swap the target, returning the old target object. 085 * @param newTarget the new target object 086 * @return the old target object 087 * @throws IllegalArgumentException if the new target is invalid 088 */ 089 public synchronized Object swap(Object newTarget) throws IllegalArgumentException { 090 Assert.notNull(newTarget, "Target object must not be null"); 091 Object old = this.target; 092 this.target = newTarget; 093 return old; 094 } 095 096 097 /** 098 * Two HotSwappableTargetSources are equal if the current target 099 * objects are equal. 100 */ 101 @Override 102 public boolean equals(Object other) { 103 return (this == other || (other instanceof HotSwappableTargetSource && 104 this.target.equals(((HotSwappableTargetSource) other).target))); 105 } 106 107 @Override 108 public int hashCode() { 109 return HotSwappableTargetSource.class.hashCode(); 110 } 111 112 @Override 113 public String toString() { 114 return "HotSwappableTargetSource for target: " + this.target; 115 } 116 117}