解决自定义securityMetadataSource不能使用依赖注入的问题,nullpointer问题,空指针问题

spring3,spring security,MySecurityMetadataSource,自定义securityMetadataSource,依赖注入,注解,注入,空指针异常,nullpointer,service



解决自定义securityMetadataSource不能使用依赖注入的问题,nullpointer问题,空指针问题  我在配置spring3Security3 的时候为了从数据库管理资源,自定义了securityMetadataSource,但是在类中使用依赖注入的话,加载applicationContext-security.xml的时候,会抛出使用依赖注入的那一行对象为null,是什么原因? 

也就是说提示依赖注入resourcesServiceImplnullpointer这里只贴出applicationContext-security.xmlMySecurityMetadataSource.java的代码。网上有很多谈到的解决方案,但是都没有解决实质问题。 这里给出我的解决方法,其实,如同异常所示: 



Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name'mySecurityMetadataSource' defined in file [E:\Program Files\Apache SoftwareFoundation\Tomcat6.0\webapps\testSpringSecure\WEB-INF\classes\com\test\security\MySecurityMetadataSource.class]:Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class[com.test.security.MySecurityMetadataSource]: Constructor threw exception;nested exception is java.lang.NullPointerException

    atorg.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:997)

    atorg.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:943)

    atorg.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485)

    atorg.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)

    atorg.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)

    atorg.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)

    atorg.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)

    atorg.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)

    atorg.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:322)

    ...53 more

Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class[com.test.security.MySecurityMetadataSource]: Constructor threw exception;nested exception is java.lang.NullPointerException

    atorg.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:162)

    atorg.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:76)

    atorg.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:990)

    ...61 more

Caused by: java.lang.NullPointerException

    atcom.test.security.MySecurityMetadataSource.loadResourceDefine(MySecurityMetadataSource.java:81)

    atcom.test.security.MySecurityMetadataSource.(MySecurityMetadataSource.java:51)

    atsun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

    atsun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)

    atsun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)

    atjava.lang.reflect.Constructor.newInstance(Constructor.java:513)

    atorg.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:147)

    ...63 more  



问题出在com.test.security.MySecurityMetadataSource.loadResourceDefine(MySecurityMetadataSource.java:81)上面。


 网上给出的大部分解决方法是在xml里面配置强制注入resourcesServiceImpl,但是这样做很不灵活,而且由于大部分代码都已经用了注解来配置注入,所以不建议使用xml再来配置注入。 那么究竟是什么原因呢?其实答案很简单,就是在MySecurityMetadataSource.java中应该把两个自定义构造器去掉。如同我在下面的注释所说: 

不要使用自定义构造方法,否则会导致注入会出错?应该是因为构造器中调用了loadResourceDefine方法,先于service注入,所以抛出异常。

 我们这里并不需要自定义构造器,因为在使用注解注入时,注入会自动进行,当你使用了自定义构造器,由于里面调用了loadResourceDefine();而构造器在注入发生前就被调用了,所以就会先执行loadResourceDefine();,此时注入还没进行,因而就会抛出空指针异常了。


applicationContext-security.xml:  


xml version="1.0"encoding="UTF-8"?>

<beans:beans xmlns="http://www.springframework.org/schema/security"

    xmlns:beans="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsd

                       http://www.springframework.org/schema/securityhttp://www.springframework.org/schema/security/spring-security-3.0.xsd">

   

                  

    <global-method-security secured-annotations="enabled" jsr250-annotations="enabled">global-method-security>

   

 

    <http access-denied-page="/access_denied.jsp"  use-expressions="true"  entry-point-ref="authenticationProcessingFilterEntryPoint">

         

        <intercept-url pattern="/js/**" filters="none"/>

         

              

        <logout invalidate-session="true" logout-url="/j_spring_security_logout"success-handler-ref="customLogoutSuccessHandler"  />

      

        

        <remember-me />

      

       

        

       <session-management invalid-session-url="/login.jsp">

           <concurrency-control max-sessions="100" error-if-maximum-exceeded="false"/>

       session-management>

       

        <custom-filter ref="loginFilter" position="FORM_LOGIN_FILTER"  />

       <custom-filter ref="securityFilter"before="FILTER_SECURITY_INTERCEPTOR"/>

    http>

 

    

    <beans:bean id="authenticationProcessingFilterEntryPoint"class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">

       <beans:property name="loginFormUrl"value="/login.jsp">beans:property>

    beans:bean>

   

    

    <beans:bean id="customLogoutSuccessHandler" class="com.test.security.CustomLogoutSuccessHandler">

      

    beans:bean>

   

   

   

    

    <beans:bean id="loginFilter"

       class="com.test.security.MyUsernamePasswordAuthenticationFilter">

       

       <beans:property name="filterProcessesUrl"value="/j_spring_security_check">beans:property>

       <beans:property name="authenticationSuccessHandler"ref="loginLogAuthenticationSuccessHandler">beans:property>

       <beans:property name="authenticationFailureHandler"ref="simpleUrlAuthenticationFailureHandler">beans:property>

       <beans:property name="authenticationManager"ref="myAuthenticationManager">beans:property>

      

    beans:bean>

    <beans:bean id="loginLogAuthenticationSuccessHandler"

        class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">

       <beans:property name="defaultTargetUrl"value="/index.jsp">beans:property>

    beans:bean>

    <beans:bean id="simpleUrlAuthenticationFailureHandler"

        class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">

       <beans:property name="defaultFailureUrl"value="/login.jsp">beans:property>

    beans:bean>

   

    

    <beans:bean id="securityFilter"class="com.test.security.MySecurityFilter">

     

     <beans:property name="authenticationManager" ref="myAuthenticationManager" />

     

     <beans:property name="accessDecisionManager" ref="myAccessDecisionManager" />

     

     <beans:property name="securityMetadataSource" ref="mySecurityMetadataSource" />

    beans:bean>

    

    <authentication-manager alias="myAuthenticationManager">

        <authentication-provider user-service-ref="myUserDetailServiceImpl"/>

    authentication-manager>

   

 

   

beans:beans>



MySecurityMetadataSource: 



package com.test.security;

import java.util.ArrayList;

import java.util.Collection;

import java.util.HashMap;

import java.util.Iterator;

import java.util.List;

import java.util.Map;

import java.util.Set;

import java.util.Map.Entry;


import javax.annotation.PostConstruct;

import javax.annotation.Resource;


import org.springframework.security.access.ConfigAttribute;

import org.springframework.security.access.SecurityConfig;

import org.springframework.security.web.FilterInvocation;

import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;

import org.springframework.stereotype.Component;


import com.test.bean.Resources;

import com.test.dao.IResourcesDao;

import com.test.service.IResourcesService;

//1 加载资源与权限的对应关系

@Component("mySecurityMetadataSource")

public class MySecurityMetadataSource implements FilterInvocationSecurityMetadataSource {

/*不要使用自定义构造方法,否则导致注入会出错?应该是构造器中调用了loadResourceDefine方法,先于service注入,所以抛出异常。

public MySecurityMetadataSource() {

loadResourceDefine();

}

//由spring调用

public MySecurityMetadataSource(IResourcesService resourcesServiceImpl) {

this.resourcesServiceImpl = resourcesServiceImpl;

loadResourceDefine();

}*/


@Resource

private IResourcesService resourcesServiceImpl;

private static Map> resourceMap = null;


public Collection getAllConfigAttributes() {

// TODO Auto-generated method stub

return null;

}


public boolean supports(Class clazz) {

// TODO Auto-generated method stub

return true;

}

//加载所有资源与权限的关系

@PostConstruct

private void loadResourceDefine() {

if(resourceMap == null) {

resourceMap = new HashMap>();

List resources = this.resourcesServiceImpl.findAll();

//List resources = new ArrayList();

for (Resources resource : resources) {

Collection configAttributes = new ArrayList();

                                //以权限名封装为Spring的security Object

ConfigAttribute configAttribute = new SecurityConfig(resource.getName());

configAttributes.add(configAttribute);

resourceMap.put(resource.getUrl(), configAttributes);

}

}

Set>> resourceSet = resourceMap.entrySet();

Iterator>> iterator = resourceSet.iterator();

System.out.println("MySecurityMetadataSource:loadResourceDefine()");

}

//返回所请求资源所需要的权限

public Collection getAttributes(Object object) throws IllegalArgumentException {

System.out.println("MySecurityMetadataSource:getAttributes()");

String requestUrl = ((FilterInvocation) object).getRequestUrl();

System.out.println("requestUrl is " + requestUrl);

if(resourceMap == null) {

loadResourceDefine();

}

Collection c = resourceMap.get(requestUrl);

System.out.println("MySecurityMetadataSource Collection:"+c);

return c;

}


}





你可能感兴趣的:(spring3)