public WebEnvironment initEnvironment(ServletContext servletContext) throws IllegalStateException {

        if (servletContext.getAttribute(ENVIRONMENT_ATTRIBUTE_KEY) != null) {
            String msg = "There is already a Shiro environment associated with the current ServletContext.  "
                    + "Check if you have multiple EnvironmentLoader* definitions in your web.xml!";
            throw new IllegalStateException(msg);
        }

        servletContext.log("Initializing Shiro environment");
        LOGGER.info("Starting Shiro environment initialization.");

        long startTime = System.currentTimeMillis();

        try {

            WebEnvironment environment = createEnvironment(servletContext);
            servletContext.setAttribute(ENVIRONMENT_ATTRIBUTE_KEY, environment);

            LOGGER.debug("Published WebEnvironment as ServletContext attribute with name [{}]",
                    ENVIRONMENT_ATTRIBUTE_KEY);

            if (LOGGER.isInfoEnabled()) {
                long elapsed = System.currentTimeMillis() - startTime;
                LOGGER.info("Shiro environment initialized in {} ms.", elapsed);
            }

            return environment;
        } catch (RuntimeException | Error ex) {
            LOGGER.error("Shiro environment initialization failed", ex);
            servletContext.setAttribute(ENVIRONMENT_ATTRIBUTE_KEY, ex);
            throw ex;
        }
    }
Initializes Shiro's {@link WebEnvironment} instance for the specified {@code ServletContext} based on the
{@link #CONFIG_LOCATIONS_PARAM} value.

@param servletContext current servlet context
@return the new Shiro {@code WebEnvironment} instance.
@throws IllegalStateException if an existing WebEnvironment has already been initialized and associated with
                              the specified {@code ServletContext}.
web/src/main/java/org/apache/shiro/web/env/EnvironmentLoader.java