@ -23,13 +23,18 @@ import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.Pointcut ;
import org.springframework.aop.Pointcut ;
import org.springframework.aop.support.AbstractPointcutAdvisor ;
import org.springframework.aop.support.AbstractPointcutAdvisor ;
import org.springframework.aop.support.StaticMethodMatcherPointcut ;
import org.springframework.aop.support.StaticMethodMatcherPointcut ;
import org.springframework.beans.BeansException ;
import org.springframework.beans.factory.BeanFactory ;
import org.springframework.beans.factory.BeanFactoryAware ;
import org.springframework.security.intercept.method.MethodDefinitionSource ;
import org.springframework.security.intercept.method.MethodDefinitionSource ;
import org.springframework.util.Assert ;
import org.springframework.util.Assert ;
/ * *
/ * *
* Advisor driven by a { @link MethodDefinitionSource } , used to exclude a { @link MethodSecurityInterceptor } from
* Advisor driven by a { @link MethodDefinitionSource } , used to exclude a { @link MethodSecurityInterceptor } from
* public ( ie non - secure ) methods . < p > Because the AOP framework caches advice calculations , this is normally faster
* public ( ie non - secure ) methods .
* than just letting the < code > MethodSecurityInterceptor < / code > run and find out itself that it has no work to do .
* < p >
* Because the AOP framework caches advice calculations , this is normally faster than just letting the
* < code > MethodSecurityInterceptor < / code > run and find out itself that it has no work to do .
* < p >
* < p >
* This class also allows the use of Spring ' s
* This class also allows the use of Spring ' s
* { @link org . springframework . aop . framework . autoproxy . DefaultAdvisorAutoProxyCreator } , which makes
* { @link org . springframework . aop . framework . autoproxy . DefaultAdvisorAutoProxyCreator } , which makes
@ -42,22 +47,47 @@ import org.springframework.util.Assert;
* @author Ben Alex
* @author Ben Alex
* @version $Id$
* @version $Id$
* /
* /
public class MethodDefinitionSourceAdvisor extends AbstractPointcutAdvisor {
public class MethodDefinitionSourceAdvisor extends AbstractPointcutAdvisor implements BeanFactoryAware {
//~ Instance fields ================================================================================================
//~ Instance fields ================================================================================================
private MethodDefinitionSource attributeSource ;
private MethodDefinitionSource attributeSource ;
private MethodSecurityInterceptor interceptor ;
private MethodSecurityInterceptor interceptor ;
private Pointcut pointcut ;
private Pointcut pointcut = new MethodDefinitionSourcePointcut ( ) ;
private BeanFactory beanFactory ;
private String adviceBeanName ;
private final Object adviceMonitor = new Object ( ) ;
//~ Constructors ===================================================================================================
//~ Constructors ===================================================================================================
/ * *
* @deprecated use the decoupled approach instead
* /
public MethodDefinitionSourceAdvisor ( MethodSecurityInterceptor advice ) {
public MethodDefinitionSourceAdvisor ( MethodSecurityInterceptor advice ) {
Assert . notNull ( advice . getObjectDefinitionSource ( ) , "Cannot construct a MethodDefinitionSourceAdvisor using a " +
"MethodSecurityInterceptor that has no ObjectDefinitionSource configured" ) ;
this . interceptor = advice ;
this . interceptor = advice ;
this . attributeSource = advice . getObjectDefinitionSource ( ) ;
}
Assert . notNull ( advice . getObjectDefinitionSource ( ) , "Cannot construct a MethodDefinitionSourceAdvisor using a MethodSecurityInterceptor that has no ObjectDefinitionSource configured" ) ;
/ * *
* Alternative constructor for situations where we want the advisor decoupled from the advice . Instead the advice
* bean name should be set . This prevents eager instantiation of the interceptor
* ( and hence the AuthenticationManager ) . See SEC - 773 , for example .
* < p >
* This is essentially the approach taken by subclasses of { @link AbstractBeanFactoryPointcutAdvisor } , which this
* class should extend in future . The original hierarchy and constructor have been retained for backwards
* compatibilty .
*
* @param adviceBeanName name of the MethodSecurityInterceptor bean
* @param attributeSource the attribute source ( should be the same as the one used on the interceptor )
* /
public MethodDefinitionSourceAdvisor ( String adviceBeanName , MethodDefinitionSource attributeSource ) {
Assert . notNull ( adviceBeanName , "The adviceBeanName cannot be null" ) ;
Assert . notNull ( attributeSource , "The attributeSource cannot be null" ) ;
this . attributeSource = advice . getObjectDefinitionSource ( ) ;
this . adviceBeanName = adviceBeanName ;
this . pointcut = new MethodDefinitionSourcePointcut ( ) ;
this . attributeSource = attributeSource ;
}
}
//~ Methods ========================================================================================================
//~ Methods ========================================================================================================
@ -67,7 +97,20 @@ public class MethodDefinitionSourceAdvisor extends AbstractPointcutAdvisor {
}
}
public Advice getAdvice ( ) {
public Advice getAdvice ( ) {
return interceptor ;
synchronized ( this . adviceMonitor ) {
if ( interceptor = = null ) {
Assert . notNull ( adviceBeanName , "'adviceBeanName' must be set for use with bean factory lookup." ) ;
Assert . state ( beanFactory ! = null , "BeanFactory must be set to resolve 'adviceBeanName'" ) ;
interceptor = ( MethodSecurityInterceptor )
beanFactory . getBean ( this . adviceBeanName , MethodSecurityInterceptor . class ) ;
attributeSource = interceptor . getObjectDefinitionSource ( ) ;
}
return interceptor ;
}
}
public void setBeanFactory ( BeanFactory beanFactory ) throws BeansException {
this . beanFactory = beanFactory ;
}
}
//~ Inner Classes ==================================================================================================
//~ Inner Classes ==================================================================================================