Search in sources :

Example 1 with AbstractExecutableMethod

use of io.micronaut.context.AbstractExecutableMethod in project micronaut-core by micronaut-projects.

the class BeanDefinitionWriter method writeInterceptedLifecycleMethod.

private void writeInterceptedLifecycleMethod(String lifeCycleMethodName, String dispatchMethodName, GeneratorAdapter targetMethodVisitor, int instanceLocalIndex) {
    // if there is method interception in place we need to construct an inner executable method class that invokes the "initialize"
    // method and apply interception
    final InnerClassDef postConstructInnerMethod = newInnerClass(AbstractExecutableMethod.class);
    // needs fields to propagate the correct arguments to the initialize method
    final ClassWriter postConstructInnerWriter = postConstructInnerMethod.innerClassWriter;
    final Type postConstructInnerClassType = postConstructInnerMethod.innerClassType;
    final String fieldBeanDef = "$beanDef";
    final String fieldResContext = "$resolutionContext";
    final String fieldBeanContext = "$beanContext";
    final String fieldBean = "$bean";
    newFinalField(postConstructInnerWriter, beanDefinitionType, fieldBeanDef);
    newFinalField(postConstructInnerWriter, TYPE_RESOLUTION_CONTEXT, fieldResContext);
    newFinalField(postConstructInnerWriter, TYPE_BEAN_CONTEXT, fieldBeanContext);
    newFinalField(postConstructInnerWriter, beanType, fieldBean);
    // constructor will be AbstractExecutableMethod(BeanDefinition, BeanResolutionContext, BeanContext, T beanType)
    final String constructorDescriptor = getConstructorDescriptor(new Type[] { beanDefinitionType, TYPE_RESOLUTION_CONTEXT, TYPE_BEAN_CONTEXT, beanType });
    GeneratorAdapter protectedConstructor = new GeneratorAdapter(postConstructInnerWriter.visitMethod(ACC_PROTECTED, CONSTRUCTOR_NAME, constructorDescriptor, null, null), ACC_PROTECTED, CONSTRUCTOR_NAME, constructorDescriptor);
    // set field $beanDef
    protectedConstructor.loadThis();
    protectedConstructor.loadArg(0);
    protectedConstructor.putField(postConstructInnerClassType, fieldBeanDef, beanDefinitionType);
    // set field $resolutionContext
    protectedConstructor.loadThis();
    protectedConstructor.loadArg(1);
    protectedConstructor.putField(postConstructInnerClassType, fieldResContext, TYPE_RESOLUTION_CONTEXT);
    // set field $beanContext
    protectedConstructor.loadThis();
    protectedConstructor.loadArg(2);
    protectedConstructor.putField(postConstructInnerClassType, fieldBeanContext, TYPE_BEAN_CONTEXT);
    // set field $bean
    protectedConstructor.loadThis();
    protectedConstructor.loadArg(3);
    protectedConstructor.putField(postConstructInnerClassType, fieldBean, beanType);
    protectedConstructor.loadThis();
    protectedConstructor.push(beanType);
    protectedConstructor.push(lifeCycleMethodName);
    invokeConstructor(protectedConstructor, AbstractExecutableMethod.class, Class.class, String.class);
    protectedConstructor.returnValue();
    protectedConstructor.visitMaxs(1, 1);
    protectedConstructor.visitEnd();
    // annotation metadata should reference to the metadata for bean definition
    final GeneratorAdapter getAnnotationMetadata = startPublicFinalMethodZeroArgs(postConstructInnerWriter, AnnotationMetadata.class, "getAnnotationMetadata");
    lookupReferenceAnnotationMetadata(getAnnotationMetadata);
    // now define the invokerInternal method
    final GeneratorAdapter invokeMethod = startPublicMethod(postConstructInnerWriter, ExecutableMethodWriter.METHOD_INVOKE_INTERNAL);
    invokeMethod.loadThis();
    // load the bean definition field
    invokeMethod.getField(postConstructInnerClassType, fieldBeanDef, beanDefinitionType);
    // load the arguments to the initialize method
    // 1st argument the resolution context
    invokeMethod.loadThis();
    invokeMethod.getField(postConstructInnerClassType, fieldResContext, TYPE_RESOLUTION_CONTEXT);
    // 2nd argument the bean context
    invokeMethod.loadThis();
    invokeMethod.getField(postConstructInnerClassType, fieldBeanContext, TYPE_BEAN_CONTEXT);
    // 3rd argument the bean
    invokeMethod.loadThis();
    invokeMethod.getField(postConstructInnerClassType, fieldBean, beanType);
    // now invoke initialize
    invokeMethod.visitMethodInsn(INVOKEVIRTUAL, beanDefinitionInternalName, lifeCycleMethodName, METHOD_DESCRIPTOR_INITIALIZE, false);
    invokeMethod.returnValue();
    invokeMethod.visitMaxs(1, 1);
    invokeMethod.visitEnd();
    // now instantiate the inner class
    targetMethodVisitor.visitTypeInsn(NEW, postConstructInnerMethod.constructorInternalName);
    targetMethodVisitor.visitInsn(DUP);
    // constructor signature is AbstractExecutableMethod(BeanDefinition, BeanResolutionContext, BeanContext, T beanType)
    // 1st argument: pass outer class instance to constructor
    targetMethodVisitor.loadThis();
    // 2nd argument: resolution context
    targetMethodVisitor.loadArg(0);
    // 3rd argument: bean context
    targetMethodVisitor.loadArg(1);
    // 4th argument: bean instance
    targetMethodVisitor.loadLocal(instanceLocalIndex);
    pushCastToType(targetMethodVisitor, beanType);
    targetMethodVisitor.visitMethodInsn(INVOKESPECIAL, postConstructInnerMethod.constructorInternalName, "<init>", constructorDescriptor, false);
    final int executableInstanceIndex = targetMethodVisitor.newLocal(Type.getType(ExecutableMethod.class));
    targetMethodVisitor.storeLocal(executableInstanceIndex);
    // now invoke MethodInterceptorChain.initialize or dispose
    // 1st argument: resolution context
    targetMethodVisitor.loadArg(0);
    // 2nd argument: bean context
    targetMethodVisitor.loadArg(1);
    // 3rd argument: this definition
    targetMethodVisitor.loadThis();
    // 4th argument: executable method instance
    targetMethodVisitor.loadLocal(executableInstanceIndex);
    // 5th argument: the bean instance
    targetMethodVisitor.loadLocal(instanceLocalIndex);
    pushCastToType(targetMethodVisitor, beanType);
    targetMethodVisitor.visitMethodInsn(INVOKESTATIC, "io/micronaut/aop/chain/MethodInterceptorChain", dispatchMethodName, METHOD_DESCRIPTOR_INTERCEPTED_LIFECYCLE, false);
    targetMethodVisitor.loadLocal(instanceLocalIndex);
}
Also used : Type(org.objectweb.asm.Type) AdvisedBeanType(io.micronaut.inject.AdvisedBeanType) AbstractExecutableMethod(io.micronaut.context.AbstractExecutableMethod) ExecutableMethod(io.micronaut.inject.ExecutableMethod) GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter) ClassWriter(org.objectweb.asm.ClassWriter) AbstractConstructorInjectionPoint(io.micronaut.context.AbstractConstructorInjectionPoint) ConstructorInjectionPoint(io.micronaut.inject.ConstructorInjectionPoint)

Aggregations

AbstractConstructorInjectionPoint (io.micronaut.context.AbstractConstructorInjectionPoint)1 AbstractExecutableMethod (io.micronaut.context.AbstractExecutableMethod)1 AdvisedBeanType (io.micronaut.inject.AdvisedBeanType)1 ConstructorInjectionPoint (io.micronaut.inject.ConstructorInjectionPoint)1 ExecutableMethod (io.micronaut.inject.ExecutableMethod)1 ClassWriter (org.objectweb.asm.ClassWriter)1 Type (org.objectweb.asm.Type)1 GeneratorAdapter (org.objectweb.asm.commons.GeneratorAdapter)1