简体   繁体   中英

Spring creating beans of same interface

Consider a package which many classes all implement an interface Policy . The Policy has one method canAccess . There are 100+ policies like MenNotAllowedPolicy , ChiledNotAllowedPolicy ,... which all implement Policy

A property file describe which policies are applied to which service, for example:

BarrowBook=MenNotAllowedPolicy
BarrowMovie=MenNotAllowedPolicy,ChiledNotAllowedPolicy

To uses these polices there is a simple loop, which gets a service name an person, loop the property file and run the polices for persons. The main part of this code is:

public canPersonAccessService(aPerson , aService){
  //the listPolicy will be read from property file
  for(String policyClassName: listPolicy){        
      Class<?> clazz = Class.forName("foo.bar.Policies"+ policyClassName);
      Policy policy = (policy) clazz.newInstance();
      policy.canAccess(aPerson);
  }
}

Although Ii can make better by catching the Policy classes but I wonder if it is possible to do it easier with Spring ?! I decided a HashMap with ClassName as a key and the class instance as value, but how can I create it ?!

This a mimic of my problem :)

Define an interface called Policy as base interface for all policy implementations

interface Policy {
    boolean canAccess(User u);
}

Have one Spring Bean for each of the policy implementations - make sure you name the bean in @Component and ensure that it matches the name used in your properties file

@Component("MenNotAllowedPolicy")
public static class MenNotAllowedPolicy implements Policy {
    public boolean canAcces(User u) {
      ...
    }
}

Make the class that checks the policies also a Spring Bean, and have Spring ApplicationContext autowired in it

@Component
public static class PolicyChecker {
    ...
    @Autowired
    private ApplicationContext appContext;
    ...
    public boolean canPersonAccessService(User person, ....) {
       for(String policyName: listPolicy) { 
          Policy policy = appContext.getBean(policyName, Policy.class);
        ....
        policy.canAccess(person);
        ....
      }
    }
}

We look up policy by the its bean name, while also ensuring that bean implements Policy interface as indicated by second parameter of getBean method.

Hope this helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM