@Override public void enhanceThisClass(final ApplicationClass applicationClass) throws Exception { final CtClass ctClass = makeClass(applicationClass); if (ctClass.isInterface()) { return; } final Map<CtField, InjectionInfo> fieldsToInject = scanForInjections(ctClass); // in all methods, replace the field accesses with a call to spring for (final CtMethod ctMethod : ctClass.getDeclaredMethods()) { ctMethod.instrument( new ExprEditor() { @Override public void edit(final FieldAccess fieldAccess) { try { final InjectionInfo injectionInfo = fieldsToInject.get(fieldAccess.getField()); if (injectionInfo != null && fieldAccess.isReader()) { switch (injectionInfo.injectionMethod) { case BY_NAME: fieldAccess.replace( "$_ = ($r)play.utils.Java.invokeStatic(play.modules.spring.Spring.class, \"getBean\", new Object[] {\"" + injectionInfo.beanName + "\"});"); break; case BY_TYPE: fieldAccess.replace( "$_ = ($r)play.utils.Java.invokeStatic(play.modules.spring.Spring.class, \"getBeanOfType\", new Object[] {$type});"); break; } } } catch (final Exception e) { Logger.error( e, "Error in SpringEnhancer. %s.%s has not been properly enhanced (fieldAccess %s).", applicationClass.name, ctMethod.getName(), fieldAccess); throw new UnexpectedException("Error enhancing injected field", e); } } }); } applicationClass.enhancedByteCode = ctClass.toBytecode(); ctClass.defrost(); }
private void preprocessMethods(CtClass cc, boolean insertLoad, boolean wrapFieldAccess) throws CannotCompileException { CtMethod[] methods = cc.getDeclaredMethods(); for (int i = 0; i < methods.length; i++) { CtMethod m = methods[i]; if (wrapFieldAccess) { m.instrument( new ExprEditor() { public void edit(FieldAccess fa) throws CannotCompileException { try { if ((fa.getField().getModifiers() & (Modifier.TRANSIENT | Modifier.STATIC)) == 0 && fa.getField().getDeclaringClass().subtypeOf(persistentInterface)) { if (fa.isWriter()) { fa.replace("{ $0.loadAndModify(); $proceed($$); }"); } // isSelfReader is my extension of JAssist, if you // use original version of JAssist comment the // branch below or replace "else if" with "else". // In first case Perst will not be able to handle // access to foreign (non-this) fields. You should use // getter/setter methods instead. // In second case access to foreign fields still will be possible, // but with significant degradation of performance and // increased code size, because in this case before ALL access // to fields of persistent capable object call of load() method // will be inserted. else if (!fa.isSelfReader()) { fa.replace("{ $0.load(); $_ = $proceed($$); }"); } } } catch (NotFoundException x) { } } }); } if (insertLoad && !"recursiveLoading".equals(m.getName()) && (m.getModifiers() & (Modifier.STATIC | Modifier.ABSTRACT)) == 0) { m.insertBefore("load();"); } } }