All Downloads are FREE. Search and download functionalities are using the official Maven repository.

infra.beans.factory.support.InstanceSupplier Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2017 - 2024 the original author or authors.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see [https://www.gnu.org/licenses/]
 */

package infra.beans.factory.support;

import java.lang.reflect.Method;
import java.util.function.Supplier;

import infra.lang.Assert;
import infra.lang.Nullable;
import infra.util.function.ThrowingBiFunction;
import infra.util.function.ThrowingSupplier;

/**
 * Specialized {@link Supplier} that can be set on a
 * {@link AbstractBeanDefinition#setInstanceSupplier(Supplier) BeanDefinition}
 * when details about the {@link RegisteredBean registered bean} are needed to
 * supply the instance.
 *
 * @param  the type of instance supplied by this supplier
 * @author Phillip Webb
 * @author Harry Yang
 * @see RegisteredBean
 * @since 4.0
 */
@FunctionalInterface
public interface InstanceSupplier extends ThrowingSupplier {

  @Override
  default T getWithException() {
    throw new IllegalStateException("No RegisteredBean parameter provided");
  }

  /**
   * Get the supplied instance.
   *
   * @param registeredBean the registered bean requesting the instance
   * @return the supplied instance
   * @throws Exception on error
   */
  T get(RegisteredBean registeredBean) throws Throwable;

  /**
   * Return the factory method that this supplier uses to create the
   * instance, or {@code null} if it is not known or this supplier uses
   * another means.
   *
   * @return the factory method used to create the instance, or {@code null}
   */
  @Nullable
  default Method getFactoryMethod() {
    return null;
  }

  /**
   * Return a composed instance supplier that first obtains the instance from
   * this supplier and then applies the {@code after} function to obtain the
   * result.
   *
   * @param  the type of output of the {@code after} function, and of the
   * composed function
   * @param after the function to apply after the instance is obtained
   * @return a composed instance supplier
   */
  default  InstanceSupplier andThen(
          ThrowingBiFunction after) {

    Assert.notNull(after, "'after' function is required");
    return new InstanceSupplier<>() {
      @Override
      public V get(RegisteredBean registeredBean) throws Throwable {
        return after.applyWithException(registeredBean, InstanceSupplier.this.get(registeredBean));
      }

      @Override
      public Method getFactoryMethod() {
        return InstanceSupplier.this.getFactoryMethod();
      }
    };
  }

  /**
   * Factory method to create an {@link InstanceSupplier} from a
   * {@link ThrowingSupplier}.
   *
   * @param  the type of instance supplied by this supplier
   * @param supplier the source supplier
   * @return a new {@link InstanceSupplier}
   */
  static  InstanceSupplier using(ThrowingSupplier supplier) {
    Assert.notNull(supplier, "Supplier is required");
    if (supplier instanceof InstanceSupplier instanceSupplier) {
      return instanceSupplier;
    }
    return registeredBean -> supplier.getWithException();
  }

  /**
   * Factory method to create an {@link InstanceSupplier} from a
   * {@link ThrowingSupplier}.
   *
   * @param  the type of instance supplied by this supplier
   * @param factoryMethod the factory method being used
   * @param supplier the source supplier
   * @return a new {@link InstanceSupplier}
   */
  static  InstanceSupplier using(@Nullable Method factoryMethod, ThrowingSupplier supplier) {
    Assert.notNull(supplier, "Supplier is required");

    if (supplier instanceof InstanceSupplier instanceSupplier &&
            instanceSupplier.getFactoryMethod() == factoryMethod) {
      return instanceSupplier;
    }

    return new InstanceSupplier<>() {
      @Override
      public T get(RegisteredBean registeredBean) throws Throwable {
        return supplier.getWithException();
      }

      @Override
      public Method getFactoryMethod() {
        return factoryMethod;
      }
    };
  }

  /**
   * Lambda friendly method that can be used to create an
   * {@link InstanceSupplier} and add post processors in a single call. For
   * example: {@code InstanceSupplier.of(registeredBean -> ...).andThen(...)}.
   *
   * @param  the type of instance supplied by this supplier
   * @param instanceSupplier the source instance supplier
   * @return a new {@link InstanceSupplier}
   */
  static  InstanceSupplier of(InstanceSupplier instanceSupplier) {
    Assert.notNull(instanceSupplier, "InstanceSupplier is required");
    return instanceSupplier;
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy