class EurekaHealthCheckHandler
		implements HealthCheckHandler, ApplicationContextAware, InitializingBean, Ordered, Lifecycle {

	private static final Map<Status, InstanceInfo.InstanceStatus> STATUS_MAPPING = new HashMap<>() {
		{
			put(Status.UNKNOWN, InstanceStatus.UNKNOWN);
			put(Status.OUT_OF_SERVICE, InstanceStatus.DOWN);
			put(Status.DOWN, InstanceStatus.DOWN);
			put(Status.UP, InstanceStatus.UP);
		}
	};

	private final StatusAggregator statusAggregator;

	private ApplicationContext applicationContext;

	private final Map<String, HealthContributor> healthContributors = new HashMap<>();

	/**
	 * {@code true} until the context is stopped.
	 */
	private boolean running = true;

	private final Map<String, ReactiveHealthContributor> reactiveHealthContributors = new HashMap<>();

	public EurekaHealthCheckHandler(StatusAggregator statusAggregator) {
		this.statusAggregator = statusAggregator;
		Assert.notNull(statusAggregator, "StatusAggregator must not be null");

	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}

	@Override
	public void afterPropertiesSet() {
		populateHealthContributors(applicationContext.getBeansOfType(HealthContributor.class));
		reactiveHealthContributors.putAll(applicationContext.getBeansOfType(ReactiveHealthContributor.class));
	}

	void populateHealthContributors(Map<String, HealthContributor> healthContributors) {
		for (Map.Entry<String, HealthContributor> entry : healthContributors.entrySet()) {
			// ignore EurekaHealthIndicator and flatten the rest of the composite
			// otherwise there is a never ending cycle of down. See gh-643
			if (entry.getValue() instanceof DiscoveryCompositeHealthContributor indicator) {
				indicator.getIndicators().forEach((name, discoveryHealthIndicator) -> {
					if (!(discoveryHealthIndicator instanceof EurekaHealthIndicator)) {
						this.healthContributors.put(name, (HealthIndicator) discoveryHealthIndicator::health);
					}
				});
			}
			else {
				this.healthContributors.put(entry.getKey(), entry.getValue());
			}
		}
	}

	@Override
	public InstanceStatus getStatus(InstanceStatus instanceStatus) {
		if (running) {
			return getHealthStatus();
		}
		else {
			// Return nothing if the context is not running, so the status held by the
			// InstanceInfo remains unchanged.
			// See gh-1571
			return null;
		}
	}

	protected InstanceStatus getHealthStatus() {
		Status status = getStatus(statusAggregator);
		return mapToInstanceStatus(status);
	}

	protected Status getStatus(StatusAggregator statusAggregator) {
		Set<Status> statusSet = new HashSet<>();
		for (HealthContributor contributor : healthContributors.values()) {
			processContributor(statusSet, contributor);
		}
		for (ReactiveHealthContributor contributor : reactiveHealthContributors.values()) {
			processContributor(statusSet, contributor);
		}
		return statusAggregator.getAggregateStatus(statusSet);
	}

	private void processContributor(Set<Status> statusSet, HealthContributor contributor) {
		if (contributor instanceof CompositeHealthContributor) {
			for (NamedContributor<HealthContributor> contrib : (CompositeHealthContributor) contributor) {
				processContributor(statusSet, contrib.getContributor());
			}
		}
		else if (contributor instanceof HealthIndicator) {
			statusSet.add(((HealthIndicator) contributor).health().getStatus());
		}
	}

	private void processContributor(Set<Status> statusSet, ReactiveHealthContributor contributor) {
		if (contributor instanceof CompositeReactiveHealthContributor) {
			for (NamedContributor<ReactiveHealthContributor> contrib : (CompositeReactiveHealthContributor) contributor) {
				processContributor(statusSet, contrib.getContributor());
			}
		}
		else if (contributor instanceof ReactiveHealthIndicator) {
			Health health = ((ReactiveHealthIndicator) contributor).health().block();
			if (health != null) {
				statusSet.add(health.getStatus());
			}
		}
	}

	protected InstanceStatus mapToInstanceStatus(Status status) {
		if (!STATUS_MAPPING.containsKey(status)) {
			return InstanceStatus.UNKNOWN;
		}
		return STATUS_MAPPING.get(status);
	}

	@Override
	public int getOrder() {<FILL_FUNCTION_BODY>}

	@Override
	public void start() {
		running = true;
	}

	@Override
	public void stop() {
		running = false;
	}

	@Override
	public boolean isRunning() {
		return true;
	}

}

		// registered with a high order priority so the close() method is invoked early
		// and *BEFORE* EurekaAutoServiceRegistration
		// (must be in effect when the registration is closed and the eureka replication
		// triggered -> health check handler is
		// consulted at that moment)
		return Ordered.HIGHEST_PRECEDENCE;
	
<no_super_class>