View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.shiro.spring;
20  
21  import org.springframework.beans.BeansException;
22  import org.springframework.beans.FatalBeanException;
23  import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
24  import org.springframework.core.PriorityOrdered;
25  
26  import org.slf4j.Logger;
27  import org.slf4j.LoggerFactory;
28  
29  import org.apache.shiro.util.Destroyable;
30  import org.apache.shiro.util.Initializable;
31  
32  
33  /**
34   * <p>Bean post processor for Spring that automatically calls the <tt>init()</tt> and/or
35   * <tt>destroy()</tt> methods on Shiro objects that implement the {@link org.apache.shiro.util.Initializable}
36   * or {@link org.apache.shiro.util.Destroyable} interfaces, respectfully.  This post processor makes it easier
37   * to configure Shiro beans in Spring, since the user never has to worry about whether or not if they
38   * have to specify init-method and destroy-method bean attributes.</p>
39   *
40   * <p><b>Warning: This post processor has no way to determine if <tt>init()</tt> or <tt>destroy()</tt> have
41   * already been called, so if you define this post processor in your applicationContext, do not also call these
42   * methods manually or via Spring's <tt>init-method</tt> or <tt>destroy-method</tt> bean attributes.</b></p>
43   *
44   * @since 0.2
45   */
46  public class LifecycleBeanPostProcessor implements DestructionAwareBeanPostProcessor, PriorityOrdered {
47  
48      /**
49       * Private internal class log instance.
50       */
51      private static final Logger log = LoggerFactory.getLogger(LifecycleBeanPostProcessor.class);
52  
53      /**
54       * Order value of this BeanPostProcessor.
55       */
56      private int order;
57  
58      /**
59       * Default Constructor.
60       */
61      public LifecycleBeanPostProcessor() {
62          this(LOWEST_PRECEDENCE);
63      }
64  
65      /**
66       * Constructor with definable {@link #getOrder() order value}.
67       *
68       * @param order order value of this BeanPostProcessor.
69       */
70      public LifecycleBeanPostProcessor(int order) {
71          this.order = order;
72      }
73  
74      /**
75       * Calls the <tt>init()</tt> methods on the bean if it implements {@link org.apache.shiro.util.Initializable}
76       *
77       * @param object the object being initialized.
78       * @param name   the name of the bean being initialized.
79       * @return the initialized bean.
80       * @throws BeansException if any exception is thrown during initialization.
81       */
82      public Object postProcessBeforeInitialization(Object object, String name) throws BeansException {
83          if (object instanceof Initializable) {
84              try {
85                  if (log.isDebugEnabled()) {
86                      log.debug("Initializing bean [" + name + "]...");
87                  }
88  
89                  ((Initializable) object).init();
90              } catch (Exception e) {
91                  throw new FatalBeanException("Error initializing bean [" + name + "]", e);
92              }
93          }
94          return object;
95      }
96  
97  
98      /**
99       * Does nothing - merely returns the object argument immediately.
100      */
101     public Object postProcessAfterInitialization(Object object, String name) throws BeansException {
102         // Does nothing after initialization
103         return object;
104     }
105 
106 
107     /**
108      * Calls the <tt>destroy()</tt> methods on the bean if it implements {@link org.apache.shiro.util.Destroyable}
109      *
110      * @param object the object being initialized.
111      * @param name   the name of the bean being initialized.
112      * @throws BeansException if any exception is thrown during initialization.
113      */
114     public void postProcessBeforeDestruction(Object object, String name) throws BeansException {
115         if (object instanceof Destroyable) {
116             try {
117                 if (log.isDebugEnabled()) {
118                     log.debug("Destroying bean [" + name + "]...");
119                 }
120 
121                 ((Destroyable) object).destroy();
122             } catch (Exception e) {
123                 throw new FatalBeanException("Error destroying bean [" + name + "]", e);
124             }
125         }
126     }
127 
128     /**
129      * Order value of this BeanPostProcessor.
130      *
131      * @return order value.
132      */
133     public int getOrder() {
134         // LifecycleBeanPostProcessor needs Order. See https://issues.apache.org/jira/browse/SHIRO-222
135         return order;
136     }
137 
138     /**
139      * Return true only if <code>bean</code> implements Destroyable.
140      * @param bean bean to check if requires destruction.
141      * @return true only if <code>bean</code> implements Destroyable.
142      * @since 1.4
143      */
144     @SuppressWarnings("unused")
145     public boolean requiresDestruction(Object bean) {
146         return (bean instanceof Destroyable);
147     }
148 }