You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shiro.apache.org by bd...@apache.org on 2016/10/14 19:36:11 UTC

[08/20] shiro git commit: SHIRO-590 - Added Spring Boot starters and programatic Spring support.

http://git-wip-us.apache.org/repos/asf/shiro/blob/cd3dde8a/support/spring-boot/spring-boot-web-starter/src/main/java/org/apache/shiro/spring/config/web/autoconfigure/ShiroWebAutoConfiguration.java
----------------------------------------------------------------------
diff --git a/support/spring-boot/spring-boot-web-starter/src/main/java/org/apache/shiro/spring/config/web/autoconfigure/ShiroWebAutoConfiguration.java b/support/spring-boot/spring-boot-web-starter/src/main/java/org/apache/shiro/spring/config/web/autoconfigure/ShiroWebAutoConfiguration.java
new file mode 100644
index 0000000..953a63e
--- /dev/null
+++ b/support/spring-boot/spring-boot-web-starter/src/main/java/org/apache/shiro/spring/config/web/autoconfigure/ShiroWebAutoConfiguration.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.spring.config.web.autoconfigure;
+
+import org.apache.shiro.authc.Authenticator;
+import org.apache.shiro.authc.pam.AuthenticationStrategy;
+import org.apache.shiro.authz.Authorizer;
+import org.apache.shiro.mgt.*;
+import org.apache.shiro.realm.Realm;
+import org.apache.shiro.session.mgt.SessionFactory;
+import org.apache.shiro.session.mgt.SessionManager;
+import org.apache.shiro.session.mgt.eis.SessionDAO;
+import org.apache.shiro.spring.web.config.AbstractShiroWebConfiguration;
+import org.apache.shiro.web.servlet.Cookie;
+import org.springframework.boot.autoconfigure.AutoConfigureOrder;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+
+import java.util.List;
+
+/**
+ * @since 1.4.0
+ */
+@Configuration
+@ConditionalOnProperty(name = "shiro.web.enabled", matchIfMissing = true)
+public class ShiroWebAutoConfiguration extends AbstractShiroWebConfiguration {
+
+    @Bean
+    @ConditionalOnMissingBean
+    @Override
+    protected AuthenticationStrategy authenticationStrategy() {
+        return super.authenticationStrategy();
+    }
+
+    @Bean
+    @ConditionalOnMissingBean
+    @Override
+    protected Authenticator authenticator() {
+        return super.authenticator();
+    }
+
+    @Bean
+    @ConditionalOnMissingBean
+    @Override
+    protected Authorizer authorizer() {
+        return super.authorizer();
+    }
+
+    @Bean
+    @ConditionalOnMissingBean
+    @Override
+    protected SubjectDAO subjectDAO() {
+        return super.subjectDAO();
+    }
+
+    @Bean
+    @ConditionalOnMissingBean
+    @Override
+    protected SessionStorageEvaluator sessionStorageEvaluator() {
+        return super.sessionStorageEvaluator();
+    }
+
+    @Bean
+    @ConditionalOnMissingBean
+    @Override
+    protected SessionFactory sessionFactory() {
+        return super.sessionFactory();
+    }
+
+    @Bean
+    @ConditionalOnMissingBean
+    @Override
+    protected SessionDAO sessionDAO() {
+        return super.sessionDAO();
+    }
+
+    @Bean
+    @ConditionalOnMissingBean(name = "sessionCookieTemplate")
+    @Override
+    protected Cookie sessionCookieTemplate() {
+        return super.sessionCookieTemplate();
+    }
+
+    @Bean
+    @ConditionalOnMissingBean
+    @Override
+    protected RememberMeManager rememberMeManager() {
+        return super.rememberMeManager();
+    }
+
+    @Bean
+    @ConditionalOnMissingBean(name = "rememberMeCookieTemplate")
+    @Override
+    protected Cookie rememberMeCookieTemplate() {
+        return super.rememberMeCookieTemplate();
+    }
+
+    @Bean
+    @ConditionalOnMissingBean
+    @Override
+    protected SubjectFactory subjectFactory() {
+        return super.subjectFactory();
+    }
+
+    @Bean
+    @ConditionalOnMissingBean
+    @Override
+    protected SessionManager sessionManager() {
+        return super.sessionManager();
+    }
+
+    @Bean
+    @ConditionalOnMissingBean
+    @Override
+    protected SessionsSecurityManager securityManager(List<Realm> realms) {
+        return super.securityManager(realms);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/cd3dde8a/support/spring-boot/spring-boot-web-starter/src/main/java/org/apache/shiro/spring/config/web/autoconfigure/ShiroWebFilterConfiguration.java
----------------------------------------------------------------------
diff --git a/support/spring-boot/spring-boot-web-starter/src/main/java/org/apache/shiro/spring/config/web/autoconfigure/ShiroWebFilterConfiguration.java b/support/spring-boot/spring-boot-web-starter/src/main/java/org/apache/shiro/spring/config/web/autoconfigure/ShiroWebFilterConfiguration.java
new file mode 100644
index 0000000..96e8ad1
--- /dev/null
+++ b/support/spring-boot/spring-boot-web-starter/src/main/java/org/apache/shiro/spring/config/web/autoconfigure/ShiroWebFilterConfiguration.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.spring.config.web.autoconfigure;
+
+import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
+import org.apache.shiro.spring.web.config.AbstractShiroWebFilterConfiguration;
+import org.apache.shiro.web.servlet.AbstractShiroFilter;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @since 1.4.0
+ */
+@Configuration
+@ConditionalOnProperty(name = "shiro.web.enabled", matchIfMissing = true)
+public class ShiroWebFilterConfiguration extends AbstractShiroWebFilterConfiguration {
+
+    @Bean
+    @ConditionalOnMissingBean
+    @Override
+    protected ShiroFilterFactoryBean shiroFilterFactoryBean() {
+        return super.shiroFilterFactoryBean();
+    }
+
+    @Bean(name = "filterShiroFilterRegistrationBean")
+    @ConditionalOnMissingBean
+    protected FilterRegistrationBean filterShiroFilterRegistrationBean() throws Exception {
+
+        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
+        filterRegistrationBean.setFilter((AbstractShiroFilter) shiroFilterFactoryBean().getObject());
+        filterRegistrationBean.setOrder(1);
+
+        return filterRegistrationBean;
+    }
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/cd3dde8a/support/spring-boot/spring-boot-web-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json
----------------------------------------------------------------------
diff --git a/support/spring-boot/spring-boot-web-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/support/spring-boot/spring-boot-web-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json
new file mode 100644
index 0000000..a5157d3
--- /dev/null
+++ b/support/spring-boot/spring-boot-web-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json
@@ -0,0 +1,46 @@
+{
+  "groups": [
+    {
+      "name": "shiro"
+    },
+  ],
+  "properties": [
+
+    {
+      "name": "shiro.web.enabled",
+      "type": "java.lang.Boolean",
+      "description": "A boolean flag that can disable all Shiro Spring Boot starters.  This is mostly useful during testing or debugging, or if you want to compare behavior when Shiro is enabled or disabled.",
+      "defaultValue": true
+    },
+    {
+      "name": "shiro.loginUrl",
+      "type": "java.lang.String",
+      "description": "The application's login URL to be assigned to all acquired Filters that subclass AccessControlFilter or 'null' if no value should be assigned globally.",
+      "defaultValue": "/login.jsp"
+    },
+    {
+      "name": "shiro.successUrl",
+      "type": "java.lang.String",
+      "description": "The application's after-login success URL to be assigned to all acquired Filters that subclass AuthenticationFilter or null if no value should be assigned globally.",
+      "defaultValue": "/"
+    },
+    {
+      "name": "shiro.unauthorizedUrl",
+      "type": "java.lang.String",
+      "description": "The application's 'unauthorized' URL to apply to as a convenience to all discovered AuthorizationFilter instances.",
+      "defaultValue": null
+    },
+    {
+      "name": "shiro.sessionManager.sessionIdCookieEnabled",
+      "type": "java.lang.String",
+      "description": "Enable or disable session tracking via a cookie.",
+      "defaultValue": true
+    },
+    {
+      "name": "shiro.sessionManager.sessionIdUrlRewritingEnabled",
+      "type": "java.lang.String",
+      "description": "Enable or disable session tracking via a URL parameter.  If your site requires cookies, it is recommended you disable this.",
+      "defaultValue": true
+    }
+  ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/shiro/blob/cd3dde8a/support/spring-boot/spring-boot-web-starter/src/main/resources/META-INF/spring.factories
----------------------------------------------------------------------
diff --git a/support/spring-boot/spring-boot-web-starter/src/main/resources/META-INF/spring.factories b/support/spring-boot/spring-boot-web-starter/src/main/resources/META-INF/spring.factories
new file mode 100644
index 0000000..397c6e4
--- /dev/null
+++ b/support/spring-boot/spring-boot-web-starter/src/main/resources/META-INF/spring.factories
@@ -0,0 +1 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration = org.apache.shiro.spring.config.web.autoconfigure.ShiroBeanAutoConfiguration,org.apache.shiro.spring.config.web.autoconfigure.ShiroWebAutoConfiguration,org.apache.shiro.spring.config.web.autoconfigure.ShiroWebFilterConfiguration,org.apache.shiro.spring.config.web.autoconfigure.ShiroAnnotationProcessorAutoConfiguration

http://git-wip-us.apache.org/repos/asf/shiro/blob/cd3dde8a/support/spring-boot/spring-boot-web-starter/src/main/resources/META-INF/spring.provides
----------------------------------------------------------------------
diff --git a/support/spring-boot/spring-boot-web-starter/src/main/resources/META-INF/spring.provides b/support/spring-boot/spring-boot-web-starter/src/main/resources/META-INF/spring.provides
new file mode 100644
index 0000000..ffe94a1
--- /dev/null
+++ b/support/spring-boot/spring-boot-web-starter/src/main/resources/META-INF/spring.provides
@@ -0,0 +1 @@
+provides: shiro-web
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/shiro/blob/cd3dde8a/support/spring-boot/spring-boot-web-starter/src/test/groovy/org/apache/shiro/spring/boot/autoconfigure/web/ShiroWebSpringAutoConfigurationTest.groovy
----------------------------------------------------------------------
diff --git a/support/spring-boot/spring-boot-web-starter/src/test/groovy/org/apache/shiro/spring/boot/autoconfigure/web/ShiroWebSpringAutoConfigurationTest.groovy b/support/spring-boot/spring-boot-web-starter/src/test/groovy/org/apache/shiro/spring/boot/autoconfigure/web/ShiroWebSpringAutoConfigurationTest.groovy
new file mode 100644
index 0000000..db1b384
--- /dev/null
+++ b/support/spring-boot/spring-boot-web-starter/src/test/groovy/org/apache/shiro/spring/boot/autoconfigure/web/ShiroWebSpringAutoConfigurationTest.groovy
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.spring.boot.autoconfigure.web
+
+import org.apache.shiro.spring.boot.autoconfigure.web.ShiroWebAutoConfigurationTestApplication.EventBusAwareObject
+import org.apache.shiro.spring.boot.autoconfigure.web.ShiroWebAutoConfigurationTestApplication.SubscribedListener
+
+import org.apache.shiro.event.EventBus
+import org.apache.shiro.mgt.DefaultSecurityManager
+import org.apache.shiro.mgt.SecurityManager
+import org.apache.shiro.web.mgt.WebSecurityManager
+import org.junit.Test
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.boot.test.context.SpringBootTest
+import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests
+
+import static org.hamcrest.MatcherAssert.assertThat
+import static org.hamcrest.Matchers.instanceOf
+import static org.junit.Assert.*
+/**
+ * @since 1.4.0
+ */
+@SpringBootTest(classes = [ShiroWebAutoConfigurationTestApplication])
+public class ShiroWebSpringAutoConfigurationTest extends AbstractJUnit4SpringContextTests {
+
+    @Autowired
+    private SecurityManager securityManager
+
+    @Autowired
+    private EventBus eventBus
+
+    @Autowired
+    private EventBusAwareObject eventBusAwareObject
+
+    @Autowired
+    private SubscribedListener subscribedListener
+
+    @Test
+    public void testMinimalConfiguration() {
+
+        // first do a quick check of the injected objects
+        assertNotNull securityManager
+        assertThat securityManager, instanceOf(WebSecurityManager)
+
+        assertNotNull eventBusAwareObject
+        assertNotNull eventBus
+        assertTrue(eventBus.registry.containsKey(subscribedListener))
+        assertSame(eventBusAwareObject.getEventBus(), eventBus)
+        assertSame(((DefaultSecurityManager)securityManager).getEventBus(), eventBus)
+
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/cd3dde8a/support/spring-boot/spring-boot-web-starter/src/test/java/org/apache/shiro/spring/boot/autoconfigure/web/ShiroWebAutoConfigurationTestApplication.java
----------------------------------------------------------------------
diff --git a/support/spring-boot/spring-boot-web-starter/src/test/java/org/apache/shiro/spring/boot/autoconfigure/web/ShiroWebAutoConfigurationTestApplication.java b/support/spring-boot/spring-boot-web-starter/src/test/java/org/apache/shiro/spring/boot/autoconfigure/web/ShiroWebAutoConfigurationTestApplication.java
new file mode 100644
index 0000000..8fdcc1a
--- /dev/null
+++ b/support/spring-boot/spring-boot-web-starter/src/test/java/org/apache/shiro/spring/boot/autoconfigure/web/ShiroWebAutoConfigurationTestApplication.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.spring.boot.autoconfigure.web;
+
+
+import org.apache.shiro.event.EventBus;
+import org.apache.shiro.event.EventBusAware;
+import org.apache.shiro.event.Subscribe;
+import org.apache.shiro.realm.Realm;
+import org.apache.shiro.realm.text.TextConfigurationRealm;
+import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
+import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@EnableAutoConfiguration
+public class ShiroWebAutoConfigurationTestApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(ShiroWebAutoConfigurationTestApplication.class, args);
+    }
+
+    @Bean
+    @SuppressWarnings("Duplicates")
+    Realm getTextConfigurationRealm() {
+
+        TextConfigurationRealm realm = new TextConfigurationRealm();
+        realm.setUserDefinitions("joe.coder=password,user\n" +
+                                 "jill.coder=password,admin");
+
+        realm.setRoleDefinitions("admin=read,write\n" +
+                                 "user=read");
+        realm.setCachingEnabled(true);
+        return realm;
+    }
+
+    @Bean
+    ShiroFilterChainDefinition shiroFilterChainDefinition() {
+        return new DefaultShiroFilterChainDefinition();
+    }
+
+    @Bean
+    EventBusAwareObject eventBusAwareObject() {
+        return new EventBusAwareObject();
+    }
+
+    @Bean
+    SubscribedListener subscribedListener() {
+        return new SubscribedListener();
+    }
+
+
+    public static class EventBusAwareObject implements EventBusAware {
+
+        private EventBus eventBus;
+
+        @Override
+        public void setEventBus(EventBus bus) {
+            this.eventBus = bus;
+        }
+
+        public EventBus getEventBus() {
+            return eventBus;
+        }
+    }
+
+    public static class SubscribedListener {
+
+        @Subscribe
+        public void onEvent(Object object) {}
+    }
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/cd3dde8a/support/spring/src/main/java/org/apache/shiro/spring/LifecycleBeanPostProcessor.java
----------------------------------------------------------------------
diff --git a/support/spring/src/main/java/org/apache/shiro/spring/LifecycleBeanPostProcessor.java b/support/spring/src/main/java/org/apache/shiro/spring/LifecycleBeanPostProcessor.java
index a526769..a318d20 100644
--- a/support/spring/src/main/java/org/apache/shiro/spring/LifecycleBeanPostProcessor.java
+++ b/support/spring/src/main/java/org/apache/shiro/spring/LifecycleBeanPostProcessor.java
@@ -134,4 +134,15 @@ public class LifecycleBeanPostProcessor implements DestructionAwareBeanPostProce
         // LifecycleBeanPostProcessor needs Order. See https://issues.apache.org/jira/browse/SHIRO-222
         return order;
     }
+
+    /**
+     * Return true only if <code>bean</code> implements Destroyable.
+     * @param bean bean to check if requires destruction.
+     * @return true only if <code>bean</code> implements Destroyable.
+     * @since 1.4
+     */
+    @SuppressWarnings("unused")
+    public boolean requiresDestruction(Object bean) {
+        return (bean instanceof Destroyable);
+    }
 }

http://git-wip-us.apache.org/repos/asf/shiro/blob/cd3dde8a/support/spring/src/main/java/org/apache/shiro/spring/ShiroEventBusBeanPostProcessor.java
----------------------------------------------------------------------
diff --git a/support/spring/src/main/java/org/apache/shiro/spring/ShiroEventBusBeanPostProcessor.java b/support/spring/src/main/java/org/apache/shiro/spring/ShiroEventBusBeanPostProcessor.java
new file mode 100644
index 0000000..64a40cf
--- /dev/null
+++ b/support/spring/src/main/java/org/apache/shiro/spring/ShiroEventBusBeanPostProcessor.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.spring;
+
+import org.apache.shiro.event.EventBus;
+import org.apache.shiro.event.EventBusAware;
+import org.apache.shiro.event.Subscribe;
+import org.apache.shiro.util.ClassUtils;
+import org.apache.shiro.util.CollectionUtils;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+
+import java.util.List;
+
+/**
+ * Spring {@link BeanPostProcessor} that detects, {@link EventBusAware} and classes containing {@link Subscribe @Subscribe} methods.
+ * Any classes implementing EventBusAware will have the setEventBus() method called with the <code>eventBus</code>. Any
+ * classes discovered with methods that are annotated with @Subscribe will be automaticly registered with the EventBus.
+ *
+ * <p><strong>NOTE:</strong> in a Spring environment implementing EventBusAware is not necessary, as you can just inject the EventBus with
+ * {@link org.springframework.beans.factory.annotation.Autowire @Autowire}.</p>
+ *
+ * @see EventBusAware
+ * @see Subscribe
+ * @since 1.4
+ */
+public class ShiroEventBusBeanPostProcessor implements BeanPostProcessor {
+
+    final private EventBus eventBus;
+
+    public ShiroEventBusBeanPostProcessor(EventBus eventBus) {
+        this.eventBus = eventBus;
+    }
+
+    @Override
+    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
+        return bean;
+    }
+
+    @Override
+    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
+        if (bean instanceof EventBusAware) {
+            ((EventBusAware) bean).setEventBus(eventBus);
+        }
+        else if (isEventSubscriber(bean)) {
+            eventBus.register(bean);
+        }
+
+        return bean;
+    }
+
+    private boolean isEventSubscriber(Object bean) {
+        List annotatedMethods = ClassUtils.getAnnotatedMethods(bean.getClass(), Subscribe.class);
+        return !CollectionUtils.isEmpty(annotatedMethods);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/cd3dde8a/support/spring/src/main/java/org/apache/shiro/spring/config/AbstractShiroAnnotationProcessorConfiguration.java
----------------------------------------------------------------------
diff --git a/support/spring/src/main/java/org/apache/shiro/spring/config/AbstractShiroAnnotationProcessorConfiguration.java b/support/spring/src/main/java/org/apache/shiro/spring/config/AbstractShiroAnnotationProcessorConfiguration.java
new file mode 100644
index 0000000..679d205
--- /dev/null
+++ b/support/spring/src/main/java/org/apache/shiro/spring/config/AbstractShiroAnnotationProcessorConfiguration.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.spring.config;
+
+
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
+import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
+
+/**
+ * @since 1.4.0
+ */
+public class AbstractShiroAnnotationProcessorConfiguration {
+
+    protected DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
+        return new DefaultAdvisorAutoProxyCreator();
+    }
+
+    protected AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
+        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
+        advisor.setSecurityManager(securityManager);
+        return advisor;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/cd3dde8a/support/spring/src/main/java/org/apache/shiro/spring/config/AbstractShiroBeanConfiguration.java
----------------------------------------------------------------------
diff --git a/support/spring/src/main/java/org/apache/shiro/spring/config/AbstractShiroBeanConfiguration.java b/support/spring/src/main/java/org/apache/shiro/spring/config/AbstractShiroBeanConfiguration.java
new file mode 100644
index 0000000..5c9753f
--- /dev/null
+++ b/support/spring/src/main/java/org/apache/shiro/spring/config/AbstractShiroBeanConfiguration.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.spring.config;
+
+import org.apache.shiro.event.EventBus;
+import org.apache.shiro.event.support.DefaultEventBus;
+import org.apache.shiro.spring.LifecycleBeanPostProcessor;
+import org.apache.shiro.spring.ShiroEventBusBeanPostProcessor;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * @since 1.4.0
+ */
+public class AbstractShiroBeanConfiguration {
+
+    protected LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
+        return new LifecycleBeanPostProcessor();
+    }
+
+    protected EventBus eventBus() {
+        return new DefaultEventBus();
+    }
+
+    protected ShiroEventBusBeanPostProcessor shiroEventBusAwareBeanPostProcessor() {
+        return new ShiroEventBusBeanPostProcessor(eventBus());
+    }
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/cd3dde8a/support/spring/src/main/java/org/apache/shiro/spring/config/AbstractShiroConfiguration.java
----------------------------------------------------------------------
diff --git a/support/spring/src/main/java/org/apache/shiro/spring/config/AbstractShiroConfiguration.java b/support/spring/src/main/java/org/apache/shiro/spring/config/AbstractShiroConfiguration.java
new file mode 100644
index 0000000..7f25178
--- /dev/null
+++ b/support/spring/src/main/java/org/apache/shiro/spring/config/AbstractShiroConfiguration.java
@@ -0,0 +1,152 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.spring.config;
+
+import org.apache.shiro.authc.Authenticator;
+import org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy;
+import org.apache.shiro.authc.pam.AuthenticationStrategy;
+import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
+import org.apache.shiro.authz.Authorizer;
+import org.apache.shiro.authz.ModularRealmAuthorizer;
+import org.apache.shiro.authz.permission.PermissionResolver;
+import org.apache.shiro.authz.permission.RolePermissionResolver;
+import org.apache.shiro.cache.CacheManager;
+import org.apache.shiro.event.EventBus;
+import org.apache.shiro.mgt.*;
+import org.apache.shiro.realm.Realm;
+import org.apache.shiro.session.mgt.DefaultSessionManager;
+import org.apache.shiro.session.mgt.SessionFactory;
+import org.apache.shiro.session.mgt.SessionManager;
+import org.apache.shiro.session.mgt.SimpleSessionFactory;
+import org.apache.shiro.session.mgt.eis.MemorySessionDAO;
+import org.apache.shiro.session.mgt.eis.SessionDAO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+
+import java.util.List;
+
+/**
+ * @since 1.4.0
+ */
+public class AbstractShiroConfiguration {
+
+    @Autowired(required = false)
+    protected CacheManager cacheManager;
+
+    @Autowired(required = false)
+    protected RolePermissionResolver rolePermissionResolver;
+
+    @Autowired(required = false)
+    protected PermissionResolver permissionResolver;
+
+    @Autowired
+    protected EventBus eventBus;
+
+    @Value("#{ @environment['shiro.sessionManager.deleteInvalidSessions'] ?: true }")
+    protected boolean sessionManagerDeleteInvalidSessions;
+
+
+    protected SessionsSecurityManager securityManager(List<Realm> realms) {
+        SessionsSecurityManager securityManager = createSecurityManager();
+        securityManager.setAuthenticator(authenticator());
+        securityManager.setAuthorizer(authorizer());
+        securityManager.setRealms(realms);
+        securityManager.setSessionManager(sessionManager());
+        securityManager.setEventBus(eventBus);
+
+        if (cacheManager != null) {
+            securityManager.setCacheManager(cacheManager);
+        }
+
+        return securityManager;
+    }
+
+    protected SessionManager sessionManager() {
+        DefaultSessionManager sessionManager = new DefaultSessionManager();
+        sessionManager.setSessionDAO(sessionDAO());
+        sessionManager.setSessionFactory(sessionFactory());
+        sessionManager.setDeleteInvalidSessions(sessionManagerDeleteInvalidSessions);
+        return sessionManager;
+    }
+
+
+    protected SessionsSecurityManager createSecurityManager() {
+        DefaultSecurityManager securityManager = new DefaultSecurityManager();
+        securityManager.setSubjectDAO(subjectDAO());
+        securityManager.setSubjectFactory(subjectFactory());
+
+        RememberMeManager rememberMeManager = rememberMeManager();
+        if (rememberMeManager != null) {
+            securityManager.setRememberMeManager(rememberMeManager);
+        }
+
+        return securityManager;
+    }
+
+    protected RememberMeManager rememberMeManager() {
+        return null;
+    }
+
+    protected SubjectDAO subjectDAO() {
+        DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
+        subjectDAO.setSessionStorageEvaluator(sessionStorageEvaluator());
+        return subjectDAO;
+    }
+
+    protected SessionStorageEvaluator sessionStorageEvaluator() {
+        return new DefaultSessionStorageEvaluator();
+    }
+
+    protected SubjectFactory subjectFactory() {
+        return new DefaultSubjectFactory();
+    }
+
+
+    protected SessionFactory sessionFactory() {
+        return new SimpleSessionFactory();
+    }
+
+    protected SessionDAO sessionDAO() {
+        return new MemorySessionDAO();
+    }
+
+    protected Authorizer authorizer() {
+        ModularRealmAuthorizer authorizer = new ModularRealmAuthorizer();
+
+        if (permissionResolver != null) {
+            authorizer.setPermissionResolver(permissionResolver);
+        }
+
+        if (rolePermissionResolver != null) {
+            authorizer.setRolePermissionResolver(rolePermissionResolver);
+        }
+
+        return authorizer;
+    }
+
+    protected AuthenticationStrategy authenticationStrategy() {
+        return new AtLeastOneSuccessfulStrategy();
+    }
+
+    protected Authenticator authenticator() {
+        ModularRealmAuthenticator authenticator = new ModularRealmAuthenticator();
+        authenticator.setAuthenticationStrategy(authenticationStrategy());
+        return authenticator;
+    }
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/cd3dde8a/support/spring/src/main/java/org/apache/shiro/spring/config/ShiroAnnotationProcessorConfiguration.java
----------------------------------------------------------------------
diff --git a/support/spring/src/main/java/org/apache/shiro/spring/config/ShiroAnnotationProcessorConfiguration.java b/support/spring/src/main/java/org/apache/shiro/spring/config/ShiroAnnotationProcessorConfiguration.java
new file mode 100644
index 0000000..d575352
--- /dev/null
+++ b/support/spring/src/main/java/org/apache/shiro/spring/config/ShiroAnnotationProcessorConfiguration.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.spring.config;
+
+
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
+import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.DependsOn;
+
+/**
+ * @since 1.4.0
+ */
+@Configuration
+public class ShiroAnnotationProcessorConfiguration extends AbstractShiroAnnotationProcessorConfiguration{
+
+    @Bean
+    @DependsOn("lifecycleBeanPostProcessor")
+    protected DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
+        return super.defaultAdvisorAutoProxyCreator();
+    }
+
+    @Bean
+    protected AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
+        return super.authorizationAttributeSourceAdvisor(securityManager);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/cd3dde8a/support/spring/src/main/java/org/apache/shiro/spring/config/ShiroBeanConfiguration.java
----------------------------------------------------------------------
diff --git a/support/spring/src/main/java/org/apache/shiro/spring/config/ShiroBeanConfiguration.java b/support/spring/src/main/java/org/apache/shiro/spring/config/ShiroBeanConfiguration.java
new file mode 100644
index 0000000..37e1321
--- /dev/null
+++ b/support/spring/src/main/java/org/apache/shiro/spring/config/ShiroBeanConfiguration.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.spring.config;
+
+import org.apache.shiro.event.EventBus;
+import org.apache.shiro.spring.LifecycleBeanPostProcessor;
+import org.apache.shiro.spring.ShiroEventBusBeanPostProcessor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @since 1.4.0
+ */
+@Configuration
+public class ShiroBeanConfiguration extends AbstractShiroBeanConfiguration {
+
+    @Bean
+    @Override
+    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
+        return super.lifecycleBeanPostProcessor();
+    }
+
+    @Bean
+    @Override
+    protected EventBus eventBus() {
+        return super.eventBus();
+    }
+
+    @Bean
+    @Override
+    public ShiroEventBusBeanPostProcessor shiroEventBusAwareBeanPostProcessor() {
+        return super.shiroEventBusAwareBeanPostProcessor();
+    }
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/cd3dde8a/support/spring/src/main/java/org/apache/shiro/spring/config/ShiroConfiguration.java
----------------------------------------------------------------------
diff --git a/support/spring/src/main/java/org/apache/shiro/spring/config/ShiroConfiguration.java b/support/spring/src/main/java/org/apache/shiro/spring/config/ShiroConfiguration.java
new file mode 100644
index 0000000..dfd7c41
--- /dev/null
+++ b/support/spring/src/main/java/org/apache/shiro/spring/config/ShiroConfiguration.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.spring.config;
+
+import org.apache.shiro.authc.Authenticator;
+import org.apache.shiro.authc.pam.AuthenticationStrategy;
+import org.apache.shiro.authz.Authorizer;
+import org.apache.shiro.event.EventBus;
+import org.apache.shiro.mgt.*;
+import org.apache.shiro.realm.Realm;
+import org.apache.shiro.session.mgt.SessionFactory;
+import org.apache.shiro.session.mgt.SessionManager;
+import org.apache.shiro.session.mgt.eis.SessionDAO;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+
+import java.util.List;
+
+/**
+ * @since 1.4.0
+ */
+@Configuration
+@Import({ShiroBeanConfiguration.class})
+public class ShiroConfiguration extends AbstractShiroConfiguration {
+
+
+    @Bean
+    @Override
+    protected SessionsSecurityManager securityManager(List<Realm> realms) {
+        return super.securityManager(realms);
+    }
+
+    @Bean
+    @Override
+    protected SessionManager sessionManager() {
+        return super.sessionManager();
+    }
+
+    @Bean
+    @Override
+    protected SubjectDAO subjectDAO() {
+        return super.subjectDAO();
+    }
+
+    @Bean
+    @Override
+    protected SessionStorageEvaluator sessionStorageEvaluator() {
+        return super.sessionStorageEvaluator();
+    }
+
+    @Bean
+    @Override
+    protected SubjectFactory subjectFactory() {
+        return super.subjectFactory();
+    }
+
+    @Bean
+    @Override
+    protected SessionFactory sessionFactory() {
+        return super.sessionFactory();
+    }
+
+    @Bean
+    @Override
+    protected SessionDAO sessionDAO() {
+        return super.sessionDAO();
+    }
+
+    @Bean
+    @Override
+    protected Authorizer authorizer() {
+        return super.authorizer();
+    }
+
+    @Bean
+    @Override
+    protected AuthenticationStrategy authenticationStrategy() {
+        return super.authenticationStrategy();
+    }
+
+    @Bean
+    @Override
+    protected Authenticator authenticator() {
+        return super.authenticator();
+    }
+
+    @Bean
+    @Override
+    protected RememberMeManager rememberMeManager() {
+        return super.rememberMeManager();
+    }
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/cd3dde8a/support/spring/src/main/java/org/apache/shiro/spring/web/config/AbstractShiroWebConfiguration.java
----------------------------------------------------------------------
diff --git a/support/spring/src/main/java/org/apache/shiro/spring/web/config/AbstractShiroWebConfiguration.java b/support/spring/src/main/java/org/apache/shiro/spring/web/config/AbstractShiroWebConfiguration.java
new file mode 100644
index 0000000..5762612
--- /dev/null
+++ b/support/spring/src/main/java/org/apache/shiro/spring/web/config/AbstractShiroWebConfiguration.java
@@ -0,0 +1,157 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.spring.web.config;
+
+import org.apache.shiro.mgt.RememberMeManager;
+import org.apache.shiro.mgt.SessionsSecurityManager;
+import org.apache.shiro.mgt.SubjectFactory;
+import org.apache.shiro.session.mgt.SessionManager;
+import org.apache.shiro.spring.config.AbstractShiroConfiguration;
+import org.apache.shiro.web.mgt.CookieRememberMeManager;
+import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
+import org.apache.shiro.web.mgt.DefaultWebSubjectFactory;
+import org.apache.shiro.web.servlet.Cookie;
+import org.apache.shiro.web.servlet.SimpleCookie;
+import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
+import org.apache.shiro.web.session.mgt.ServletContainerSessionManager;
+import org.springframework.beans.factory.annotation.Value;
+
+/**
+ * @since 1.4.0
+ */
+public class AbstractShiroWebConfiguration extends AbstractShiroConfiguration {
+
+    @Value("#{ @environment['shiro.sessionManager.sessionIdCookieEnabled'] ?: true }")
+    protected boolean sessionIdCookieEnabled;
+
+    @Value("#{ @environment['shiro.sessionManager.sessionIdUrlRewritingEnabled'] ?: true }")
+    protected boolean sessionIdUrlRewritingEnabled;
+
+    @Value("#{ @environment['shiro.userNativeSessionManager'] ?: false }")
+    protected boolean useNativeSessionManager;
+
+
+    // Session Cookie info
+
+    @Value("#{ @environment['shiro.sessionManager.cookie.name'] ?: T(org.apache.shiro.web.servlet.ShiroHttpSession).DEFAULT_SESSION_ID_NAME }")
+    protected String sessionIdCookieName;
+
+    @Value("#{ @environment['shiro.sessionManager.cookie.maxAge'] ?: T(org.apache.shiro.web.servlet.SimpleCookie).DEFAULT_MAX_AGE }")
+    protected int sessionIdCookieMaxAge;
+
+    @Value("#{ @environment['shiro.sessionManager.cookie.domain'] ?: null }")
+    protected String sessionIdCookieDomain;
+
+    @Value("#{ @environment['shiro.sessionManager.cookie.path'] ?: null }")
+    protected String sessionIdCookiePath;
+
+    @Value("#{ @environment['shiro.sessionManager.cookie.secure'] ?: false }")
+    protected boolean sessionIdCookieSecure;
+
+
+    // RememberMe Cookie info
+
+    @Value("#{ @environment['shiro.rememberMeManager.cookie.name'] ?: T(org.apache.shiro.web.mgt.CookieRememberMeManager).DEFAULT_REMEMBER_ME_COOKIE_NAME }")
+    protected String rememberMeCookieName;
+
+    @Value("#{ @environment['shiro.rememberMeManager.cookie.maxAge'] ?: T(org.apache.shiro.web.servlet.Cookie).ONE_YEAR }")
+    protected int rememberMeCookieMaxAge;
+
+    @Value("#{ @environment['shiro.rememberMeManager.cookie.domain'] ?: null }")
+    protected String rememberMeCookieDomain;
+
+    @Value("#{ @environment['shiro.rememberMeManager.cookie.path'] ?: null }")
+    protected String rememberMeCookiePath;
+
+    @Value("#{ @environment['shiro.rememberMeManager.cookie.secure'] ?: false }")
+    protected boolean rememberMeCookieSecure;
+
+
+    protected SessionManager nativeSessionManager() {
+        DefaultWebSessionManager webSessionManager = new DefaultWebSessionManager();
+        webSessionManager.setSessionIdCookieEnabled(sessionIdCookieEnabled);
+        webSessionManager.setSessionIdUrlRewritingEnabled(sessionIdUrlRewritingEnabled);
+        webSessionManager.setSessionIdCookie(sessionCookieTemplate());
+
+        webSessionManager.setSessionFactory(sessionFactory());
+        webSessionManager.setSessionDAO(sessionDAO());
+        webSessionManager.setDeleteInvalidSessions(sessionManagerDeleteInvalidSessions);
+
+        return webSessionManager;
+    }
+
+    protected Cookie sessionCookieTemplate() {
+        return buildCookie(
+                sessionIdCookieName,
+                sessionIdCookieMaxAge,
+                sessionIdCookiePath,
+                sessionIdCookieDomain,
+                sessionIdCookieSecure);
+    }
+
+    protected Cookie rememberMeCookieTemplate() {
+        return buildCookie(
+                rememberMeCookieName,
+                rememberMeCookieMaxAge,
+                rememberMeCookiePath,
+                rememberMeCookieDomain,
+                rememberMeCookieSecure);
+    }
+
+    protected Cookie buildCookie(String name, int maxAge, String path, String domain, boolean secure) {
+        Cookie cookie = new SimpleCookie(name);
+        cookie.setHttpOnly(true);
+        cookie.setMaxAge(maxAge);
+        cookie.setPath(path);
+        cookie.setDomain(domain);
+        cookie.setSecure(secure);
+
+        return cookie;
+    }
+
+    @Override
+    protected SessionManager sessionManager() {
+        if (useNativeSessionManager) {
+            return nativeSessionManager();
+        }
+        return new ServletContainerSessionManager();
+    }
+
+    protected RememberMeManager rememberMeManager() {
+        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
+        cookieRememberMeManager.setCookie(rememberMeCookieTemplate());
+        return cookieRememberMeManager;
+    }
+
+    @Override
+    protected SubjectFactory subjectFactory() {
+        return new DefaultWebSubjectFactory();
+    }
+
+    protected SessionsSecurityManager createSecurityManager() {
+
+        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
+        securityManager.setSubjectDAO(subjectDAO());
+        securityManager.setSubjectFactory(subjectFactory());
+        securityManager.setRememberMeManager(rememberMeManager());
+
+        return securityManager;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/cd3dde8a/support/spring/src/main/java/org/apache/shiro/spring/web/config/AbstractShiroWebFilterConfiguration.java
----------------------------------------------------------------------
diff --git a/support/spring/src/main/java/org/apache/shiro/spring/web/config/AbstractShiroWebFilterConfiguration.java b/support/spring/src/main/java/org/apache/shiro/spring/web/config/AbstractShiroWebFilterConfiguration.java
new file mode 100644
index 0000000..fb12601
--- /dev/null
+++ b/support/spring/src/main/java/org/apache/shiro/spring/web/config/AbstractShiroWebFilterConfiguration.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.spring.web.config;
+
+
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+
+/**
+ * @since 1.4.0
+ */
+public class AbstractShiroWebFilterConfiguration {
+
+    @Autowired
+    protected SecurityManager securityManager;
+
+    @Autowired
+    protected ShiroFilterChainDefinition shiroFilterChainDefinition;
+
+    @Value("#{ @environment['shiro.loginUrl'] ?: '/login.jsp' }")
+    protected String loginUrl;
+
+    @Value("#{ @environment['shiro.successUrl'] ?: '/' }")
+    protected String successUrl;
+
+    @Value("#{ @environment['shiro.unauthorizedUrl'] ?: null }")
+    protected String unauthorizedUrl;
+
+    protected ShiroFilterFactoryBean shiroFilterFactoryBean() {
+        ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean();
+
+        filterFactoryBean.setLoginUrl(loginUrl);
+        filterFactoryBean.setSuccessUrl(successUrl);
+        filterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);
+
+        filterFactoryBean.setSecurityManager(securityManager);
+        filterFactoryBean.setFilterChainDefinitionMap(shiroFilterChainDefinition.getFilterChainMap());
+
+        return filterFactoryBean;
+    }
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/cd3dde8a/support/spring/src/main/java/org/apache/shiro/spring/web/config/DefaultShiroFilterChainDefinition.java
----------------------------------------------------------------------
diff --git a/support/spring/src/main/java/org/apache/shiro/spring/web/config/DefaultShiroFilterChainDefinition.java b/support/spring/src/main/java/org/apache/shiro/spring/web/config/DefaultShiroFilterChainDefinition.java
new file mode 100644
index 0000000..bbd3f60
--- /dev/null
+++ b/support/spring/src/main/java/org/apache/shiro/spring/web/config/DefaultShiroFilterChainDefinition.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.spring.web.config;
+
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @since 1.4.0
+ */
+public class DefaultShiroFilterChainDefinition implements ShiroFilterChainDefinition {
+
+    final private Map<String, String> filterChainDefinitionMap = new HashMap<String, String>();
+
+    public void addPathDefinition(String antPath, String definition) {
+        filterChainDefinitionMap.put(antPath, definition);
+    }
+
+    public void addPathDefinitions(Map<String, String> pathDefinitions) {
+        filterChainDefinitionMap.putAll(pathDefinitions);
+    }
+
+    @Override
+    public Map<String, String> getFilterChainMap() {
+        return filterChainDefinitionMap;
+    }
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/cd3dde8a/support/spring/src/main/java/org/apache/shiro/spring/web/config/ShiroFilterChainDefinition.java
----------------------------------------------------------------------
diff --git a/support/spring/src/main/java/org/apache/shiro/spring/web/config/ShiroFilterChainDefinition.java b/support/spring/src/main/java/org/apache/shiro/spring/web/config/ShiroFilterChainDefinition.java
new file mode 100644
index 0000000..fe9f5d6
--- /dev/null
+++ b/support/spring/src/main/java/org/apache/shiro/spring/web/config/ShiroFilterChainDefinition.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.spring.web.config;
+
+import java.util.Map;
+
+/**
+ * @since 1.4.0
+ */
+public interface ShiroFilterChainDefinition {
+
+    Map<String, String> getFilterChainMap();
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/cd3dde8a/support/spring/src/main/java/org/apache/shiro/spring/web/config/ShiroWebConfiguration.java
----------------------------------------------------------------------
diff --git a/support/spring/src/main/java/org/apache/shiro/spring/web/config/ShiroWebConfiguration.java b/support/spring/src/main/java/org/apache/shiro/spring/web/config/ShiroWebConfiguration.java
new file mode 100644
index 0000000..e3bb516
--- /dev/null
+++ b/support/spring/src/main/java/org/apache/shiro/spring/web/config/ShiroWebConfiguration.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.spring.web.config;
+
+import org.apache.shiro.authc.Authenticator;
+import org.apache.shiro.authc.pam.AuthenticationStrategy;
+import org.apache.shiro.authz.Authorizer;
+import org.apache.shiro.mgt.*;
+import org.apache.shiro.realm.Realm;
+import org.apache.shiro.session.mgt.SessionFactory;
+import org.apache.shiro.session.mgt.SessionManager;
+import org.apache.shiro.session.mgt.eis.SessionDAO;
+import org.apache.shiro.web.servlet.Cookie;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.DependsOn;
+
+import java.util.List;
+
+/**
+ * @since 1.4.0
+ */
+@Configuration
+public class ShiroWebConfiguration extends AbstractShiroWebConfiguration {
+
+    @Bean
+    @Override
+    protected SubjectDAO subjectDAO() {
+        return super.subjectDAO();
+    }
+
+    @Bean
+    @Override
+    protected SessionStorageEvaluator sessionStorageEvaluator() {
+        return super.sessionStorageEvaluator();
+    }
+
+    @Bean
+    @Override
+    protected SessionFactory sessionFactory() {
+        return super.sessionFactory();
+    }
+
+    @Bean
+    @Override
+    protected SessionDAO sessionDAO() {
+        return super.sessionDAO();
+    }
+
+    @Bean(name = "sessionCookieTemplate")
+    @Override
+    protected Cookie sessionCookieTemplate() {
+        return super.sessionCookieTemplate();
+    }
+
+    @Bean(name = "rememberMeCookieTemplate")
+    @Override
+    protected Cookie rememberMeCookieTemplate() {
+        return super.rememberMeCookieTemplate();
+    }
+
+    @Bean
+    @Override
+    protected RememberMeManager rememberMeManager() {
+        return super.rememberMeManager();
+    }
+
+    @Bean
+    @Override
+    protected SubjectFactory subjectFactory() {
+        return super.subjectFactory();
+    }
+
+    @Bean
+    @Override
+    protected Authorizer authorizer() {
+        return super.authorizer();
+    }
+
+    @Bean
+    @Override
+    protected AuthenticationStrategy authenticationStrategy() {
+        return super.authenticationStrategy();
+    }
+
+    @Bean
+    @Override
+    protected Authenticator authenticator() {
+        return super.authenticator();
+    }
+
+    @Bean
+    @Override
+    protected SessionManager sessionManager() {
+        return super.sessionManager();
+    }
+
+    @Bean
+    @Override
+    protected SessionsSecurityManager securityManager(List<Realm> realms) {
+        return super.securityManager(realms);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/cd3dde8a/support/spring/src/main/java/org/apache/shiro/spring/web/config/ShiroWebFilterConfiguration.java
----------------------------------------------------------------------
diff --git a/support/spring/src/main/java/org/apache/shiro/spring/web/config/ShiroWebFilterConfiguration.java b/support/spring/src/main/java/org/apache/shiro/spring/web/config/ShiroWebFilterConfiguration.java
new file mode 100644
index 0000000..72a4ecb
--- /dev/null
+++ b/support/spring/src/main/java/org/apache/shiro/spring/web/config/ShiroWebFilterConfiguration.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.spring.web.config;
+
+import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @since 1.4.0
+ */
+@Configuration
+public class ShiroWebFilterConfiguration extends AbstractShiroWebFilterConfiguration {
+
+    @Bean
+    @Override
+    protected ShiroFilterFactoryBean shiroFilterFactoryBean() {
+        return super.shiroFilterFactoryBean();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/cd3dde8a/support/spring/src/test/groovy/org/apache/shiro/spring/config/ShiroBeanConfigurationTest.groovy
----------------------------------------------------------------------
diff --git a/support/spring/src/test/groovy/org/apache/shiro/spring/config/ShiroBeanConfigurationTest.groovy b/support/spring/src/test/groovy/org/apache/shiro/spring/config/ShiroBeanConfigurationTest.groovy
new file mode 100644
index 0000000..6c9b893
--- /dev/null
+++ b/support/spring/src/test/groovy/org/apache/shiro/spring/config/ShiroBeanConfigurationTest.groovy
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.spring.config
+
+import org.apache.shiro.event.EventBus
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.test.context.ContextConfiguration
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner
+
+import static org.junit.Assert.*
+
+/**
+ * @since 1.4.0
+ */
+@ContextConfiguration(classes = [ShiroBeanConfiguration, EventBusConsumersTestConfiguration])
+@RunWith(SpringJUnit4ClassRunner.class)
+public class ShiroBeanConfigurationTest {
+
+    @Autowired
+    private EventBus eventBus;
+
+    @Autowired
+    private EventBusConsumersTestConfiguration.EventBusAwareObject eventBusAwareObject;
+
+    @Autowired
+    private EventBusConsumersTestConfiguration.EventSubscriber eventSubscriber;
+
+    @Test
+    public void testBasicUsage() {
+
+        assertNotNull eventBus
+        assertNotNull eventBusAwareObject
+        assertNotNull eventSubscriber
+
+        assertTrue eventBus.registry.containsKey(eventSubscriber)
+        assertSame(eventBus, eventBusAwareObject.eventBus)
+
+    }
+
+
+
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/cd3dde8a/support/spring/src/test/groovy/org/apache/shiro/spring/config/ShiroConfigurationTest.groovy
----------------------------------------------------------------------
diff --git a/support/spring/src/test/groovy/org/apache/shiro/spring/config/ShiroConfigurationTest.groovy b/support/spring/src/test/groovy/org/apache/shiro/spring/config/ShiroConfigurationTest.groovy
new file mode 100644
index 0000000..12640e5
--- /dev/null
+++ b/support/spring/src/test/groovy/org/apache/shiro/spring/config/ShiroConfigurationTest.groovy
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.spring.config
+
+import org.apache.shiro.authc.UsernamePasswordToken
+import org.apache.shiro.authz.ModularRealmAuthorizer
+import org.apache.shiro.event.EventBus
+import org.apache.shiro.mgt.DefaultSecurityManager
+import org.apache.shiro.mgt.SecurityManager
+import org.apache.shiro.realm.text.TextConfigurationRealm
+import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor
+import org.apache.shiro.subject.Subject
+import org.junit.Assert
+import org.junit.Test
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.test.context.ContextConfiguration
+import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests
+
+import static org.hamcrest.MatcherAssert.assertThat
+import static org.hamcrest.Matchers.*
+import static org.junit.Assert.*
+
+/**
+ * @since 1.4.0
+ */
+@ContextConfiguration(classes = [RealmTestConfiguration, ShiroConfiguration])
+public class ShiroConfigurationTest extends AbstractJUnit4SpringContextTests {
+
+    @Autowired
+    private SecurityManager securityManager
+
+    @Autowired
+    private EventBus eventBus;
+
+    @Test
+    public void testMinimalConfiguration() {
+
+        // first do a quick check of the injected objects
+        assertNotNull securityManager
+        assertThat securityManager.realms, allOf(hasSize(1), hasItem(instanceOf(TextConfigurationRealm)))
+        assertNull securityManager.cacheManager
+
+        assertSame(((DefaultSecurityManager)securityManager).getEventBus(), eventBus)
+
+        def defaultSecurityManager = (DefaultSecurityManager) securityManager
+        def authorizor = (ModularRealmAuthorizer) defaultSecurityManager.getAuthorizer();
+        assertNull authorizor.rolePermissionResolver
+        assertNull authorizor.permissionResolver
+
+        // now lets do a couple quick permission tests to make sure everything has been initialized correctly.
+        Subject joeCoder = new Subject.Builder(securityManager).buildSubject()
+        joeCoder.login(new UsernamePasswordToken("joe.coder", "password"))
+        joeCoder.checkPermission("read")
+        assertTrue joeCoder.hasRole("user")
+        assertFalse joeCoder.hasRole("admin")
+        joeCoder.logout()
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/cd3dde8a/support/spring/src/test/groovy/org/apache/shiro/spring/config/ShiroConfigurationWithOptionalComponentsTest.groovy
----------------------------------------------------------------------
diff --git a/support/spring/src/test/groovy/org/apache/shiro/spring/config/ShiroConfigurationWithOptionalComponentsTest.groovy b/support/spring/src/test/groovy/org/apache/shiro/spring/config/ShiroConfigurationWithOptionalComponentsTest.groovy
new file mode 100644
index 0000000..ec42297
--- /dev/null
+++ b/support/spring/src/test/groovy/org/apache/shiro/spring/config/ShiroConfigurationWithOptionalComponentsTest.groovy
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.spring.config
+
+import org.apache.shiro.authc.UsernamePasswordToken
+import org.apache.shiro.authz.ModularRealmAuthorizer
+import org.apache.shiro.mgt.DefaultSecurityManager
+import org.apache.shiro.mgt.SecurityManager
+import org.apache.shiro.realm.text.TextConfigurationRealm
+import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor
+import org.apache.shiro.subject.Subject
+import org.junit.Test
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.test.context.ContextConfiguration
+import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests
+
+import static org.junit.Assert.*
+import static org.hamcrest.Matchers.*
+import static org.hamcrest.MatcherAssert.*
+
+/**
+ * @since 1.4.0
+ */
+@ContextConfiguration(classes = [RealmTestConfiguration, OptionalComponentsTestConfiguration, ShiroConfiguration, ShiroAnnotationProcessorConfiguration])
+public class ShiroConfigurationWithOptionalComponentsTest extends AbstractJUnit4SpringContextTests {
+
+    @Autowired
+    private SecurityManager securityManager
+
+    @Autowired
+    private AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor
+
+    @Test
+    public void testMinimalConfiguration() {
+
+        // first do a quick check of the injected objects
+        assertNotNull authorizationAttributeSourceAdvisor
+        assertNotNull securityManager
+        assertSame securityManager, authorizationAttributeSourceAdvisor.securityManager
+        assertThat securityManager.realms, allOf(hasSize(1), hasItem(instanceOf(TextConfigurationRealm)))
+        assertNotNull securityManager.cacheManager
+
+        def defaultSecurityManager = (DefaultSecurityManager) securityManager
+        def authorizor = (ModularRealmAuthorizer) defaultSecurityManager.getAuthorizer();
+        assertNotNull authorizor.rolePermissionResolver
+        assertNotNull authorizor.permissionResolver
+
+        // now lets do a couple quick permission tests to make sure everything has been initialized correctly.
+        Subject joeCoder = new Subject.Builder(securityManager).buildSubject()
+        joeCoder.login(new UsernamePasswordToken("joe.coder", "password"))
+        joeCoder.checkPermission("read")
+        assertTrue joeCoder.hasRole("user")
+        assertFalse joeCoder.hasRole("admin")
+        joeCoder.logout()
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/cd3dde8a/support/spring/src/test/groovy/org/apache/shiro/spring/config/ShiroEventBusAwareBeanPostProcessorTest.groovy
----------------------------------------------------------------------
diff --git a/support/spring/src/test/groovy/org/apache/shiro/spring/config/ShiroEventBusAwareBeanPostProcessorTest.groovy b/support/spring/src/test/groovy/org/apache/shiro/spring/config/ShiroEventBusAwareBeanPostProcessorTest.groovy
new file mode 100644
index 0000000..b4224a1
--- /dev/null
+++ b/support/spring/src/test/groovy/org/apache/shiro/spring/config/ShiroEventBusAwareBeanPostProcessorTest.groovy
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.spring.config
+
+import org.apache.shiro.event.EventBus
+import org.apache.shiro.event.EventBusAware
+import org.apache.shiro.spring.ShiroEventBusBeanPostProcessor
+import org.junit.Assert
+import org.junit.Test
+
+import static org.easymock.EasyMock.*
+
+/**
+ * Tests for {@link org.apache.shiro.spring.ShiroEventBusBeanPostProcessor}
+ */
+class ShiroEventBusAwareBeanPostProcessorTest {
+
+    @Test
+    void testPostConstructNonAware() {
+
+        def eventBus = createStrictMock(EventBus)
+        def bean = createStrictMock(Object)
+
+        replay eventBus, bean
+
+        def postProcessor = new ShiroEventBusBeanPostProcessor(eventBus);
+        def resultAfter = postProcessor.postProcessAfterInitialization(bean, "bean")
+        def resultBefore = postProcessor.postProcessBeforeInitialization(bean, "bean")
+
+        verify eventBus, bean
+        Assert.assertSame resultAfter, bean
+        Assert.assertSame resultBefore, bean
+    }
+
+    @Test
+    void testPostConstructWithEventBusAware() {
+
+        def eventBus = createStrictMock(EventBus)
+        def bean = createStrictMock(EventBusAware)
+        bean.eventBus = eventBus
+
+        replay eventBus, bean
+
+        def postProcessor = new ShiroEventBusBeanPostProcessor(eventBus);
+        def resultAfter = postProcessor.postProcessAfterInitialization(bean, "bean")
+        def resultBefore = postProcessor.postProcessBeforeInitialization(bean, "bean")
+
+        verify eventBus, bean
+        Assert.assertSame resultAfter, bean
+        Assert.assertSame resultBefore, bean
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/cd3dde8a/support/spring/src/test/groovy/org/apache/shiro/spring/web/config/ShiroWebConfigurationTest.groovy
----------------------------------------------------------------------
diff --git a/support/spring/src/test/groovy/org/apache/shiro/spring/web/config/ShiroWebConfigurationTest.groovy b/support/spring/src/test/groovy/org/apache/shiro/spring/web/config/ShiroWebConfigurationTest.groovy
new file mode 100644
index 0000000..6031deb
--- /dev/null
+++ b/support/spring/src/test/groovy/org/apache/shiro/spring/web/config/ShiroWebConfigurationTest.groovy
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.spring.web.config
+
+import org.apache.shiro.event.EventBus
+import org.apache.shiro.event.support.DefaultEventBus
+import org.apache.shiro.mgt.SecurityManager
+import org.apache.shiro.realm.text.TextConfigurationRealm
+import org.apache.shiro.spring.config.EventBusTestConfiguration
+import org.apache.shiro.spring.config.RealmTestConfiguration
+import org.apache.shiro.spring.config.ShiroAnnotationProcessorConfiguration
+import org.apache.shiro.spring.config.ShiroBeanConfiguration
+import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor
+import org.apache.shiro.web.mgt.CookieRememberMeManager
+import org.apache.shiro.web.mgt.WebSecurityManager
+import org.apache.shiro.web.servlet.Cookie
+
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.beans.factory.annotation.Qualifier
+import org.springframework.expression.Expression
+import org.springframework.expression.ExpressionParser
+import org.springframework.expression.spel.standard.SpelExpressionParser
+import org.springframework.test.context.ContextConfiguration
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner
+
+import static org.hamcrest.MatcherAssert.assertThat
+import static org.hamcrest.Matchers.*
+import static org.junit.Assert.*
+
+/**
+ * @since 1.4.0
+ */
+@ContextConfiguration(classes = [EventBusTestConfiguration, RealmTestConfiguration, ShiroWebConfiguration])
+@RunWith(SpringJUnit4ClassRunner.class)
+public class ShiroWebConfigurationTest {
+
+    @Autowired
+    private SecurityManager securityManager
+
+    @Autowired
+    @Qualifier("rememberMeCookieTemplate")
+    private Cookie rememberMeCookie;
+
+    @Autowired
+    @Qualifier("sessionCookieTemplate")
+    private Cookie sessionCookieTemplate;
+
+    @Test
+    public void testMinimalConfiguration() {
+
+        // first do a quick check of the injected objects
+        assertNotNull securityManager
+        assertThat securityManager, instanceOf(WebSecurityManager)
+        assertThat securityManager.realms, allOf(hasSize(1), hasItem(instanceOf(TextConfigurationRealm)))
+        assertNull securityManager.cacheManager
+
+
+//        // now lets do a couple quick permission tests to make sure everything has been initialized correctly.
+//        Subject joeCoder = new Subject.Builder(securityManager).buildSubject()
+//        joeCoder.login(new UsernamePasswordToken("joe.coder", "password"))
+//        joeCoder.checkPermission("read")
+//        assertTrue joeCoder.hasRole("user")
+//        assertFalse joeCoder.hasRole("admin")
+//        joeCoder.logout()
+    }
+
+    @Test
+    public void fakeCookie() {
+        ExpressionParser parser = new SpelExpressionParser();
+        Expression exp = parser.parseExpression("T(org.apache.shiro.web.mgt.CookieRememberMeManager).DEFAULT_REMEMBER_ME_COOKIE_NAME");
+//        Expression exp = parser.parseExpression("@environment['shiro.rememberMeManager.cookie.name'] ?: T(org.apache.shiro.web.mgt.CookieRememberMeManager).DEFAULT_REMEMBER_ME_COOKIE_NAME");
+
+        String message = (String) exp.getValue();
+
+        println(message);
+    }
+
+    @Test
+    public void rememberMeCookie() {
+        assertEquals "rememberMe", rememberMeCookie.name
+    }
+
+    @Test
+    public void sessionCookie() {
+        assertSame "JSESSIONID", sessionCookieTemplate.name
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/cd3dde8a/support/spring/src/test/groovy/org/apache/shiro/spring/web/config/ShiroWebConfigurationWithCacheTest.groovy
----------------------------------------------------------------------
diff --git a/support/spring/src/test/groovy/org/apache/shiro/spring/web/config/ShiroWebConfigurationWithCacheTest.groovy b/support/spring/src/test/groovy/org/apache/shiro/spring/web/config/ShiroWebConfigurationWithCacheTest.groovy
new file mode 100644
index 0000000..296b519
--- /dev/null
+++ b/support/spring/src/test/groovy/org/apache/shiro/spring/web/config/ShiroWebConfigurationWithCacheTest.groovy
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.spring.web.config
+
+import org.apache.shiro.mgt.SecurityManager
+import org.apache.shiro.realm.text.TextConfigurationRealm
+import org.apache.shiro.spring.config.EventBusTestConfiguration
+import org.apache.shiro.spring.config.RealmTestConfiguration
+import org.apache.shiro.spring.config.ShiroAnnotationProcessorConfiguration
+import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor
+import org.junit.Assert
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.test.context.ContextConfiguration
+import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner
+
+import static org.hamcrest.MatcherAssert.assertThat
+import static org.hamcrest.Matchers.*
+
+/**
+ * @since 1.4.0
+ */
+@ContextConfiguration(classes = [EventBusTestConfiguration, RealmTestConfiguration, CacheManagerConfiguration, ShiroWebConfiguration])
+@RunWith(SpringJUnit4ClassRunner.class)
+public class ShiroWebConfigurationWithCacheTest {
+
+    @Autowired
+    private SecurityManager securityManager
+
+    @Test
+    public void testMinimalConfiguration() {
+
+        // first do a quick check of the injected objects
+        Assert.assertNotNull securityManager
+        assertThat securityManager.realms, allOf(hasSize(1), hasItem(instanceOf(TextConfigurationRealm)))
+        Assert.assertNotNull securityManager.cacheManager
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/cd3dde8a/support/spring/src/test/java/org/apache/shiro/spring/config/EventBusConsumersTestConfiguration.java
----------------------------------------------------------------------
diff --git a/support/spring/src/test/java/org/apache/shiro/spring/config/EventBusConsumersTestConfiguration.java b/support/spring/src/test/java/org/apache/shiro/spring/config/EventBusConsumersTestConfiguration.java
new file mode 100644
index 0000000..83d35be
--- /dev/null
+++ b/support/spring/src/test/java/org/apache/shiro/spring/config/EventBusConsumersTestConfiguration.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.spring.config;
+
+
+import org.apache.shiro.event.EventBus;
+import org.apache.shiro.event.EventBusAware;
+import org.apache.shiro.event.Subscribe;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class EventBusConsumersTestConfiguration {
+
+    @Bean
+    protected EventBusAwareObject eventBusAwareObject() {
+        return new EventBusAwareObject();
+    }
+
+    @Bean
+    protected EventSubscriber subscriber(){
+        return new EventSubscriber();
+    }
+
+    public class EventBusAwareObject implements EventBusAware {
+
+        private EventBus eventBus;
+
+        public EventBus getEventBus() {
+            return eventBus;
+        }
+
+        public void setEventBus(EventBus eventBus) {
+            this.eventBus = eventBus;
+        }
+    }
+
+    public class EventSubscriber {
+
+        @Subscribe
+        public void listen(Object object) {}
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/cd3dde8a/support/spring/src/test/java/org/apache/shiro/spring/config/EventBusTestConfiguration.java
----------------------------------------------------------------------
diff --git a/support/spring/src/test/java/org/apache/shiro/spring/config/EventBusTestConfiguration.java b/support/spring/src/test/java/org/apache/shiro/spring/config/EventBusTestConfiguration.java
new file mode 100644
index 0000000..2050b0f
--- /dev/null
+++ b/support/spring/src/test/java/org/apache/shiro/spring/config/EventBusTestConfiguration.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.spring.config;
+
+
+import org.apache.shiro.event.EventBus;
+import org.apache.shiro.event.support.DefaultEventBus;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class EventBusTestConfiguration {
+
+    @Bean
+    protected EventBus eventBus() {
+        return new DefaultEventBus();
+    }
+
+
+
+}