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);
}
Aggregations