Spring 3 - 基于另一个对象属性在运行时动态自动装配

apr*_*tha 14 spring spring-mvc

我正在开发一个Spring 3.1 MVC应用程序,对于我的一个场景,我不得不编写两个DAO实现.我想知道如何基于另一个对象的属性在服务层中自动装配它.

例如,

    class Vehicle {
        private name;
        private type;
        ..
        ..
        ..
    } 

    @Service
    class VehicleServiceImpl implements VehicleService {

            // There are two implementations to this DAO
            // if Vehicle.type == "CAR", inject CarDAO
            // if Vehicle.type == "TRAIN", inject TrainDAO 
            @Autowired
            private VehicleDAO vehicleDAO ;

    }

    @Repository
    class CarDAO implements VehicleDAO {

    }

    @Repository
    class TrainDAO implements VehicleDAO {

    }
Run Code Online (Sandbox Code Playgroud)

如果我的车辆是汽车,我需要自动装载CarDAO,如果是火车,我需要自动装载TrainDAO

在3.1版本中实现这一点的最佳方法是什么?

我希望使用上下文属性占位符或@Qualifier注释,但这些都是基于某些属性限制查找.我不知道如何在运行时基于另一个对象的属性执行此操作.

Fel*_*ert 19

我的解决方案如下:

一个方法isResponsibleFor在VehicleDao界面:

interface VehicleDao {
    public boolean isResponsibleFor(Vehicle vehicle);
}
Run Code Online (Sandbox Code Playgroud)

示例实现:

@Repository
class CarDAO implements VehicleDAO {
    public boolean isResponsibleFor(Vehicle vehicle) {
        return "CAR".equals(vehicle.getType());
    }
}
Run Code Online (Sandbox Code Playgroud)

然后自动装载VehicleService中所有VehicleDao实现的列表:

public class VehicleServiceImpl implements VehicleService {

    @Autowired
    private List<VehicleDao> vehicleDaos;

    private VehicleDao daoForVehicle(Vehicle vehicle) {
         foreach(VehicleDao vehicleDao : vehicleDaos) {
              if(vehicleDao.isResponsibleFor(vehicle) {
                   return vehicleDao;
              }
         }

         throw new UnsupportedOperationException("unsupported vehicleType");
    }

    @Transactional
    public void save(Vehicle vehicle) {
         daoForVehicle(vehicle).save(vehicle);
    }
}
Run Code Online (Sandbox Code Playgroud)

这样做的好处是,您在以后添加新的vehicleType时无需修改服务 - 您只需添加一个新的VehicleDao实现.


Pra*_*cer 15

有一个更清洁的选择来完成这一战略.我们知道Spring很聪明,可以在它看到一个可以控制的bean的地方注入,所以当它看到你VehicleDAO的一个@Autowire或一个@Resource注释时,它会正确地注入那个具体的实现.

记住这一点,这可以在你要求Spring执行依赖注入的任何地方,使用Map<>或者List<>例如.

// Injects the map will all VehicleDAO implementations where key = the
// concrete implementation (The default name is the class name, otherwise you 
// can specify the name explicitly).
@Autowired
private Map<String, VehicleDAO> vehicleDAO;

// When you want to use a specific implementaion of VehicleDAO, just call the  
// 'get()' method on the map as in:
...
vehicleDAO.get("carDAO").yourMethod();
...
Run Code Online (Sandbox Code Playgroud)