001 /*****************************************************************************
002 * Copyright (C) PicoContainer Organization. All rights reserved. *
003 * ------------------------------------------------------------------------- *
004 * The software in this package is published under the terms of the BSD *
005 * style license a copy of which has been included with this distribution in *
006 * the LICENSE.txt file. *
007 * *
008 * Original code by *
009 *****************************************************************************/
010 package org.picocontainer.injectors;
011
012 import org.picocontainer.ComponentMonitor;
013 import org.picocontainer.Parameter;
014 import org.picocontainer.LifecycleStrategy;
015 import org.picocontainer.behaviors.PropertyApplicator;
016 import org.picocontainer.behaviors.Cached;
017
018 import java.lang.reflect.Method;
019 import java.lang.reflect.AccessibleObject;
020 import java.lang.reflect.InvocationTargetException;
021
022 /**
023 * Instantiates components using empty constructors and
024 * <a href="http://picocontainer.org/setter-injection.html">Setter Injection</a>.
025 * For easy setting of primitive properties, also see {@link PropertyApplicator}.
026 * <p/>
027 * <em>
028 * Note that this class doesn't cache instances. If you want caching,
029 * use a {@link Cached} around this one.
030 * </em>
031 * </p>
032 *
033 * @author Aslak Hellesøy
034 * @author Jörg Schaible
035 * @author Mauro Talevi
036 * @author Paul Hammant
037 */
038 @SuppressWarnings("serial")
039 public class SetterInjector<T> extends IterativeInjector<T> {
040
041 private final String setterMethodPrefix;
042
043 /**
044 * Constructs a SetterInjector
045 *
046 * @param componentKey the search key for this implementation
047 * @param componentImplementation the concrete implementation
048 * @param parameters the parameters to use for the initialization
049 * @param monitor the component monitor used by this addAdapter
050 * @param lifecycleStrategy the component lifecycle strategy used by this addAdapter
051 * @param setterMethodPrefix
052 * @throws org.picocontainer.injectors.AbstractInjector.NotConcreteRegistrationException
053 * if the implementation is not a concrete class.
054 * @throws NullPointerException if one of the parameters is <code>null</code>
055 */
056 public SetterInjector(final Object componentKey,
057 final Class componentImplementation,
058 Parameter[] parameters,
059 ComponentMonitor monitor,
060 LifecycleStrategy lifecycleStrategy,
061 String setterMethodPrefix, boolean useNames) throws NotConcreteRegistrationException {
062 super(componentKey, componentImplementation, parameters, monitor, lifecycleStrategy, useNames);
063 this.setterMethodPrefix = setterMethodPrefix;
064 }
065
066 protected Object memberInvocationReturn(Object lastReturn, AccessibleObject member, Object instance) {
067 return member != null && ((Method)member).getReturnType()!=void.class ? lastReturn : instance;
068 }
069
070 protected Object injectIntoMember(AccessibleObject member, Object componentInstance, Object toInject)
071 throws IllegalAccessException, InvocationTargetException {
072 return ((Method)member).invoke(componentInstance, toInject);
073 }
074
075 protected boolean isInjectorMethod(Method method) {
076 String methodName = method.getName();
077 return methodName.length() >= getInjectorPrefix().length() + 1 && methodName.startsWith(getInjectorPrefix()) && Character.isUpperCase(methodName.charAt(getInjectorPrefix().length()));
078 }
079
080 protected String getInjectorPrefix() {
081 return setterMethodPrefix;
082 }
083
084 public String getDescriptor() {
085 return "SetterInjector-";
086 }
087
088
089 }