Spring FactoryBean的使用

我碰到一个比较纳闷的问题:
我定义了一个类为:

Java code
/**

  • AcegiCacheManagerFactoryBean 负责初始化缓存后生成AcegiCacheManager
  • 调用 authenticationService 来获取资源和用户实例,并加入UserCache 和 ResourceCache 中
  • @author zhanghg
    *
    */
    public class AcegiCacheManagerFactoryBean implements FactoryBean,InitializingBean {

        protected final Log logger = LogFactory.getLog(getClass());
    
        private AcegiCacheManager acegiCacheManager;
        private AuthenticationService authenticationService;
        private UserCache userCache;
        private ResourceCache resourceCache;
    
        public Object getObject() throws Exception {
                return this.acegiCacheManager;
        }
    
        @SuppressWarnings("unchecked")
        public Class getObjectType() {
                return (this.acegiCacheManager != null ? this.acegiCacheManager.getClass() : AcegiCacheManager.class);
        }
    
        public boolean isSingleton() {
                return true;
        }
    
        public void afterPropertiesSet() throws Exception {
                logger.info("Initializing SecurityCacheManager");
                Assert.notNull(userCache,"userCache should not be null");
                Assert.notNull(resourceCache,"resourceCache should not be null");
                Assert.notNull(authenticationService,"Authentication Service should not be null");
    
                //初始化缓存
                List<Staff> users =authenticationService.getUsers();
                for (Iterator iter = users.iterator(); iter.hasNext();) {
                        UserDetails user = (UserDetails) iter.next();
                        userCache.putUserInCache(user);
                }
                List<Resource> rescs =authenticationService.getResources();
                for (Iterator iter = rescs.iterator(); iter.hasNext();) {
                        Resource resc = (Resource) iter.next();
                        resourceCache.putResourceInCache(resc);
                }
                //生成 acegiCacheManager
                this.acegiCacheManager = new AcegiCacheManager(userCache,resourceCache);
        }
    
        //-------------setters-----------
    
        public void setAcegiCacheManager(AcegiCacheManager acegiCacheManager) {
                this.acegiCacheManager = acegiCacheManager;
        }
    
        @Required
        public void setAuthenticationService(AuthenticationService authenticationService) {
                this.authenticationService = authenticationService;
        }
    
        @Required
        public void setUserCache(UserCache userCache) {
                this.userCache = userCache;
        }
        @Required
        public void setResourceCache(ResourceCache resourceCache) {
                this.resourceCache = resourceCache;
        }
    

}

同时还定义了一个类为:
[code=Java]
/**

  • AcegiCacheManager是对缓存进行统一管理,以屏蔽其它类对缓存的直接操作
  • 对缓存中的用户和资源进行初始化、增、删、改、清空等操作
  • @author zhanghg
    *
    */
    public class AcegiCacheManager {

    private UserCache userCache;
    private ResourceCache resourceCache;
    
    //rescTypeMapp 映射资源类型对应的资源的一对多关系,以便快速查找。
    //如method类型对应哪些资源实例,url资源类型对应哪些资源实例
    private Map<String,List<String>> rescTypeMapping;
    
    //-----constructor using fields
    @SuppressWarnings("unchecked")
    public AcegiCacheManager(UserCache userCache, ResourceCache resourceCache) {
        System.out.println("实例化SecurityManager");
            this.userCache = userCache;
            this.resourceCache = resourceCache;
    
            // 获取所有的资源,以初始化 rescTypeMapping
            rescTypeMapping = new HashMap<String,List<String>>();
            List<String> resclist = resourceCache.getAllResources();
            for (Iterator iter = resclist.iterator(); iter.hasNext();) {
                    String resString = (String) iter.next();
                    System.out.println("初始化SecurityCacheManager时取得资源信息的path:"+resString);
                    ResourceDetails resc = resourceCache.getResourceFromCache(resString);
                    System.out.println("输出该资源的type类型为:"+resc.getResourceType());
                    List<String> typelist = rescTypeMapping.get(resc.getResourceType());
                    if(typelist==null){
                            typelist = new ArrayList<String>();
                            rescTypeMapping.put(resc.getResourceType(), typelist);
                    }
                    typelist.add(resString);
            }
            System.out.println("输出最终的resTypeMapping信息:"+rescTypeMapping.size());
    }
    
    //-----get from cache methods
    public UserDetails getUser(String username) {
            return userCache.getUserFromCache(username);
    }
    
    public ResourceDetails getResourceFromCache(String resString) {
            return resourceCache.getResourceFromCache(resString);
    }
    
    //-----remove from cache methods
    public void removeUser(String username){
            userCache.removeUserFromCache(username);
    }
    
    public void removeResource(String resString){
            ResourceDetails rd = resourceCache.getResourceFromCache(resString);
            List<String> typelist = rescTypeMapping.get(rd.getResourceType());
            typelist.remove(resString);
            resourceCache.removeResourceFromCache(resString);
    }
    
    //------add to cache methods
    public void addUser(String username, String password, boolean enabled, boolean accountNonExpired,
                boolean credentialsNonExpired, boolean accountNonLocked, GrantedAuthority[] authorities){
            User user = new User(username, password, enabled, accountNonExpired,
                        credentialsNonExpired, accountNonLocked, authorities);
            addUser(user);
    }
    
    public void addUser(UserDetails user){
        System.out.println("进来,添加user至缓存");
            userCache.putUserInCache(user);
    }
    
    public void addResource(String resourceName,String resString, String resType, GrantedAuthority[] authorities){
            Resource rd = new Resource(resourceName,resString, resType, authorities);
            addResource(rd);
    }
    
    public void addResource(ResourceDetails rd){
            List<String> typelist = rescTypeMapping.get(rd.getResourceType());
            if(typelist==null){
                    typelist = new ArrayList<String>();
                    rescTypeMapping.put(rd.getResourceType(), typelist);
            }
            typelist.add(rd.getPath());
            resourceCache.putResourceInCache(rd);
    }
    
    //      ------renovate cache methods
    public void renovateUser(String orgUsername, String username, String password, boolean enabled, boolean accountNonExpired,
            boolean credentialsNonExpired, boolean accountNonLocked, GrantedAuthority[] authorities){
            removeUser(orgUsername);
            addUser(username, password, enabled, accountNonExpired,
                        credentialsNonExpired, accountNonLocked, authorities);
    }
    
    public void renovateUser(String orgUsername, UserDetails user){
            removeUser(orgUsername);
            addUser(user);
    }
    
    public void renovateResource(String resName,String orgResString,String resString, String resType, GrantedAuthority[] authorities ){
            removeResource(orgResString);
            addResource(resName,resString, resType, authorities);
    }
    
    public void renovateResource(String orgResString,ResourceDetails rd){
            removeResource(orgResString);
            addResource(rd);
    }
    
    //-------getters and setters-------------------
    public void clearResources() {
            rescTypeMapping = new HashMap<String,List<String>>();
            resourceCache.removeAllResources();
    }
    
    public void setResourceCache(ResourceCache resourceCache) {
            this.resourceCache = resourceCache;
    }
    
    public void setUserCache(UserCache userCache) {
            this.userCache = userCache;
    }
    
    /**
     * 根据资源类型,在rescTypeMapping职工获取所有该类型资源的对应的resource string
     * @param resType
     * @return List
     */
    public List<String> getResourcesByType(String resType) {
            return rescTypeMapping.get(resType);
    }
    
    /**
     * 获取所有资源的对应的resource string
     * @return
     */
    public List<String> getAllResources(){
            return resourceCache.getAllResources();
    }
    
    /**
     * 获取所有用户实例对应的user name
     * @return
     */
    @SuppressWarnings("unchecked")
    public List<String> getAllUsers(){
            EhCacheBasedUserCache ehUserCache = (EhCacheBasedUserCache)userCache;
            return ehUserCache.getCache().getKeys();
    }
    

}

[/code]

同时我的一个类:StaffManager中要用到AcegiCacheManager类
public class StaffManager {

// 统一定义所有HQL
private static final String QUERY_ADMIN_HQL = "select staff from Staff staff  join staff.roles as role where role.roleName=?";
private final Logger logger = LoggerFactory.getLogger(StaffManager.class);

//自动装配该bean的属性
@Autowired
private StaffDao staffDao;  
@Autowired
private RoleDao roleDao;    
@Autowired
private PrivilegeDao privilegeDao;  
@Autowired
private ResourceDao resourceDao;
private AcegiCacheManager acegiCacheManager;

通过@Reqiured进行了注解.

其中我在配置文件配置了bean:

但是为什么staffManager当中,取到的acegiCacheManager老是null呢?
当然通过上下文的getBean("acegiCacheManager")是可以取到这个类的,不是null
[b]问题补充:[/b]
楼上的还还是不明白:
如果通过在xml文件中注册bean:

那么我应该在staffManager中怎样写才能取得不为null啊?

而如果我通过@Component("acegiCacheManager")进行注解,
我在staffManager中进行@Autowired,但是为什么提示:
Could not autowire field: private com.sdcncsi.security.cache.manager.AcegiCacheManager,com.sdcncsi.service.sys.StaffManager注解错误?
我该 怎样做?

另外factory bean会在服务启动时自动的启动这个bean吗?
而AcegiCacheManager是在AcegiCacheManagerFactoryBean中使用的,但是如果在其它类中我们怎样来引用它,直接注入AcegiCacheManager吗?但是这个类没有默认构造方法,不能实例化.
我现在都晕了,搞的好头大,请各位大人帮忙啊.
[b]问题补充:[/b]

lovewhzlq说通过这样改定就可以:

@Autowired
private ResourceDao resourceDao;
@Autowired
private AcegiCacheManager acegiCacheManager;


我试了后不行:
1)我的配置文件中配置了:

它 是指向工厂类的,这样在启动的时候可以初始化信息.
后来,我把AcegiCacheManagerFactoryBean进行了@Component("acegiCacheManager")
并且在StaffManager中对 AcegiCacheManager acegiCacheManager 启用@Autowired,
提示:Could not autowire field:
rror creating bean with name 'acegiCacheManager': FactoryBean which is currently in creation returned null from getObject

我该如何做才对啊?

public class StaffManager {

// 统一定义所有HQL
private static final String QUERY_ADMIN_HQL = "select staff from Staff staff join staff.roles as role where role.roleName=?";
private final Logger logger = LoggerFactory.getLogger(StaffManager.class);

//自动装配该bean的属性
@Autowired
private StaffDao staffDao;
@Autowired
private RoleDao roleDao;
@Autowired
private PrivilegeDao privilegeDao;
@Autowired
private ResourceDao resourceDao;
private AcegiCacheManager acegiCacheManager;

这个bean你还是用xml配置文件的方式配置,不要用@Autowired,

为什么会报这个错Could not autowire field: private com.sdcncsi.security.cache.manager.AcegiCacheManager,

那是因为StaffManager 必须设置成依赖于

这个bean初始化属性都设置成功之后,acegiCacheManager这个属性才不为null,不然的话,
public Object getObject() throws Exception {
return this.acegiCacheManager;
} 这个工厂bean的这个方法调用得到的就是null

你改用xml配置,设置一下依赖关系

@Autowired
private ResourceDao resourceDao;
private AcegiCacheManager acegiCacheManager;
你是不是在应该这样写啊

@Autowired
private ResourceDao resourceDao;
[color=red]@Autowired
private AcegiCacheManager acegiCacheManager; [/color]

  1. 你没有通过设置@Autowired 来实现自动注入。

  2. 通过getContext("")能取到也说明你已在配置文件中进行配置。

按楼上的就可以解决。