/** * Registers all methods annotated with @Suscriber on the object * @param suscriberInstance */ private static List<EventBusSubscriptionDefinition> createEventSubscriptions(final String componentId, final Component subscriberInstance, final AopPlugin aopPlugin) { Assertion.checkNotNull(subscriberInstance); //----- //1. search all methods return Stream.of(aopPlugin.unwrap(subscriberInstance).getClass().getMethods()) .filter(method -> method.isAnnotationPresent(EventBusSubscribed.class)) .map(method -> { Assertion.checkArgument(void.class.equals(method.getReturnType()), "subscriber's methods of class {0} must be void instead of {1}", subscriberInstance.getClass(), method.getReturnType()); Assertion.checkArgument(method.getName().startsWith("on"), "subscriber's methods of class {0} must start with on", subscriberInstance.getClass()); Assertion.checkArgument(method.getParameterTypes().length == 1, "subscriber's methods of class {0} must be void onXXX(Event e)", subscriberInstance.getClass()); Assertion.checkArgument(Event.class.isAssignableFrom(method.getParameterTypes()[0]), "subscriber's methods of class {0} must be 'void onXXX(E extends Event)'", subscriberInstance.getClass()); //----- //2. For each method register a listener final Class<? extends Event> eventType = (Class<? extends Event>) method.getParameterTypes()[0]; final String subscriptionName = "EVT_" + StringUtil.camelToConstCase(componentId) + "$" + StringUtil.camelToConstCase(eventType.getSimpleName()); return new EventBusSubscriptionDefinition<>(subscriptionName, eventType, event -> ClassUtil.invoke(subscriberInstance, method, event)); }) .collect(Collectors.toList()); }
private <C extends Component> C injectAspects(final C instance, final Class implClass) { //2. AOP , a new instance is created when aspects are injected in the previous instance final Map<Method, List<Aspect>> joinPoints = ComponentAspectUtil.createAspectsByMethod(implClass, aspects); if (!joinPoints.isEmpty()) { return aopPlugin.wrap(instance, joinPoints); } return instance; }
private List<DaemonDefinition> createDaemonDefinitions(final Component component, final AopPlugin aopPlugin) { return Stream.of(aopPlugin.unwrap(component).getClass().getMethods()) .filter(method -> method.isAnnotationPresent(DaemonScheduled.class)) .map( method -> { Assertion.checkState(method.getParameterTypes().length == 0, "Method {0} on component {1} cannot have any parameter to be used as a daemon", method.getName(), component.getClass().getName()); //--- final DaemonScheduled daemonSchedule = method.getAnnotation(DaemonScheduled.class); final Supplier<Daemon> daemonSupplier; if (daemonSchedule.analytics()) { // if analytics is enabled (by default) we trace the execution with a tracer daemonSupplier = () -> () -> analyticsManager.trace( "daemon", daemonSchedule.name(), tracer -> ClassUtil.invoke(component, method)); } else { // otherwise we just execute it daemonSupplier = () -> () -> ClassUtil.invoke(component, method); } return new DaemonDefinition( daemonSchedule.name(), daemonSupplier, daemonSchedule.periodInSeconds()); }) .collect(Collectors.toList()); }
/** * Registers all methods annotated with @Metrics */ public static List<MetricDefinition> createMetricDefinitions(final String componentId, final Component component, final AopPlugin aopPlugin) { Assertion.checkNotNull(component); //-- we construct a map of feature by componentId final Map<String, String> featureByComponentId = new HashMap<>(); Home.getApp().getConfig().getModuleConfigs() .forEach(moduleConfig -> moduleConfig.getComponentConfigs() .forEach(componentConfig -> featureByComponentId.put(componentConfig.getId(), moduleConfig.getName()))); //----- //1. search all methods return Stream.of(aopPlugin.unwrap(component).getClass().getMethods()) .filter(method -> method.isAnnotationPresent(Metrics.class)) .map(method -> { Assertion.checkArgument(List.class.isAssignableFrom(method.getReturnType()), "metrics supplier methods of class {0} must return a List of Metric instead of {1}", component.getClass(), method.getReturnType()); Assertion.checkArgument(method.getParameterTypes().length == 0, "metrics supplier methods of class {0} must not have any parameter", component.getClass()); //----- //2. For each method register a listener // we remove # because it doesn't comply with definition naming rule final String metricDefinitionName = "MET_" + StringUtil.camelToConstCase(componentId.replaceAll("#", "")) + "$" + StringUtil.camelToConstCase(method.getName()); return new MetricDefinition( metricDefinitionName, () -> (List<Metric>) ClassUtil.invoke(component, method)); }) .collect(Collectors.toList()); }
return Stream.of(aopPlugin.unwrap(component).getClass().getMethods()) .filter(method -> method.isAnnotationPresent(HealthChecked.class)) .map(method -> {
@Test public final void testUnwrapp() { final AopPlugin aopPlugin = getApp().getConfig().getBootConfig().getAopPlugin(); final F f = getApp().getComponentSpace().resolve(F.class); // Il y a des aspects sur la classe donc elle doit être dewrappable assertNotEquals(F.class.getName(), f.getClass().getName()); assertEquals(F.class.getName(), aopPlugin.unwrap(f).getClass().getName()); // Il y a pas d'aspect final A myA = getApp().getComponentSpace().resolve(A.class); assertEquals(A.class.getName(), myA.getClass().getName()); assertEquals(A.class.getName(), aopPlugin.unwrap(myA).getClass().getName()); }