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

infra.beans.support.BeanInstantiatorGenerator 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.support;

import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;

import infra.bytecode.ClassVisitor;
import infra.bytecode.Opcodes;
import infra.bytecode.Type;
import infra.bytecode.commons.MethodSignature;
import infra.bytecode.core.ClassEmitter;
import infra.bytecode.core.ClassGenerator;
import infra.bytecode.core.CodeEmitter;
import infra.bytecode.core.EmitUtils;
import infra.bytecode.core.MethodInfo;
import infra.lang.Assert;
import infra.logging.LoggerFactory;
import infra.reflect.GeneratorSupport;
import infra.util.ReflectionUtils;

/**
 * {@link BeanInstantiator} bytecode Generator
 *
 * @author TODAY 2020/9/11 16:51
 */
class BeanInstantiatorGenerator extends GeneratorSupport implements ClassGenerator {

  private static final String superType = "Linfra/beans/support/ConstructorAccessor;";
  private static final MethodInfo newInstanceInfo = MethodInfo.from(
          ReflectionUtils.getMethod(ConstructorAccessor.class, "doInstantiate", Object[].class));

  /** @since 4.0 */
  private static final MethodSignature SIG_CONSTRUCTOR
          = new MethodSignature(MethodSignature.CONSTRUCTOR_NAME, "(Ljava/lang/reflect/Constructor;)V");

  private final Constructor targetConstructor;

  public BeanInstantiatorGenerator(Constructor constructor) {
    this(constructor, constructor.getDeclaringClass());
  }

  public BeanInstantiatorGenerator(Constructor constructor, Class targetClass) {
    super(targetClass);
    Assert.notNull(constructor, "constructor is required");
    this.targetConstructor = constructor;
  }

  @Override
  protected int getArgsIndex() {
    return 1;
  }

  /**
   * @since 4.0
   */
  @Override
  protected void generateConstructor(ClassEmitter ce) {
    CodeEmitter e = ce.beginMethod(Opcodes.ACC_PUBLIC, SIG_CONSTRUCTOR);
    e.loadThis();
    e.loadArg(0);
    e.super_invoke_constructor(SIG_CONSTRUCTOR);
    e.returnValue();
    e.end_method();
  }

  /**
   * Fast call bean's {@link java.lang.reflect.Constructor Constructor}
   */
  @Override
  public void generateClass(ClassVisitor visitor) {
    ClassEmitter classEmitter = beginClass(visitor);
//    Method constructor = Method.fromConstructor(targetConstructor);
//    GeneratorAdapter generator = new GeneratorAdapter(ACC_PUBLIC | ACC_FINAL, constructor, null, null, visitor);
//    generator.loadThis();

    CodeEmitter codeEmitter = EmitUtils.beginMethod(
            classEmitter, newInstanceInfo, Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL);

    Type type = Type.forClass(targetClass);
    codeEmitter.newInstance(type);
    codeEmitter.dup();

    prepareParameters(codeEmitter, this.targetConstructor);

    MethodSignature signature = MethodSignature.from(this.targetConstructor);
    codeEmitter.invokeConstructor(type, signature);

    codeEmitter.returnValue();
    codeEmitter.end_method();
    classEmitter.endClass();
  }

  /**
   * @throws NoSuchMethodException handle in fallback {@link #fallback(Exception)}
   * @since 4.0
   */
  @Override
  protected ConstructorAccessor newInstance(Class accessorClass) throws NoSuchMethodException {
    Constructor constructor = accessorClass.getDeclaredConstructor(Constructor.class);
    return ReflectionUtils.invokeConstructor(constructor, new Object[] { this.targetConstructor });
  }

  @Override
  protected ConstructorAccessor fallback(Exception exception) {
    LoggerFactory.getLogger(BeanInstantiatorGenerator.class)
            .warn("Cannot access a Constructor: [{}], using fallback instance", targetConstructor, exception);
    return super.fallback(exception);
  }

  @Override
  protected ConstructorAccessor fallbackInstance() {
    return BeanInstantiator.forReflective(targetConstructor);
  }

  @Override
  protected boolean cannotAccess() {
    return Modifier.isPrivate(targetClass.getModifiers())
            || Modifier.isPrivate(targetConstructor.getModifiers());
  }

  @Override
  protected ClassGenerator getClassGenerator() {
    return this;
  }

  @Override
  protected Object cacheKey() {
    return targetConstructor;
  }

  @Override
  protected void appendClassName(StringBuilder builder) {
    builder.append('$').append("class"); // 使用 'class' 代替
    buildClassNameSuffix(builder, targetConstructor);
  }

  @Override
  public String getSuperType() {
    return superType;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy