15

私は Spring 3.1 MVC アプリケーションに取り組んでおり、私のシナリオの 1 つで、DAO の 2 つの実装を作成する必要がありました。別のオブジェクトの属性に基づいて、サービス レイヤーでこれを自動配線する方法を知りたいです。

例えば、

    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 {

    }

車両が車の場合は CarDAO を自動配線する必要があり、電車の場合は TrainDAO を自動配線する必要があります

これをSpring 3.1で実装する最良の方法は何ですか.

コンテキスト プロパティのプレース ホルダーまたは @Qualifier アノテーションのいずれかを使用することを望んでいましたが、これらはどちらも、いくつかのプロパティに基づくルックアップに制限されています。別のオブジェクトのプロパティに基づいて実行時にこれを行う方法がわかりません。

4

4 に答える 4

22

私の解決策は次のとおりです。

VehicleDao インターフェイスのメソッド isResponsibleFor:

interface VehicleDao {
    public boolean isResponsibleFor(Vehicle vehicle);
}

実装例:

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

次に、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);
    }
}

これには、後で新しい vehicleType を追加するときにサービスを変更する必要がないという利点があります。新しい VehicleDao 実装を追加するだけで済みます。

于 2013-03-08T03:38:13.703 に答える
17

この戦略を達成するためのよりクリーンなオプションがあります。Spring は、制御できる Bean を見つけた場所に注入するのに十分なほどスマートであることを知っているため、 orアノテーションであなたVehicleDAOを見つけると、その具体的な実装を正しく注入します。@Autowire@Resource

そのことを念頭に置いて、これは、たとえば aMap<>または aList<>を使用して、Spring に依存性注入を実行するように要求する場所であればどこでも機能します。

// 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();
...
于 2015-02-11T14:17:38.850 に答える
0

Vehicleは@Modelランタイム値であるため、自動配線値に使用することはできません。

車両は引数としてサービスメソッドに渡される必要があります。

パブリックインターフェイスVehicleService{voiddoSomething(Vehicle Vehicle); }

両方が同じサービスを実装しているCarDaoと仮定すると、そうでない場合はあまり意味がありません。TrainDAOVehicleDao

したがって、あなたの中で、daoの正しいインスタンスを取得するVehicleServiceImplようなメソッドを作成することをお勧めします。getVehicleDao(Vehicle v){}

public class VehicleServiceImpl implements VehicleService {

    @Resource(name="carDAO")
    private VehicleDao carDAO ;


    @Resource(name="trainDAO")
    private VehicleDao trainDAO ;

    private VehicleDao getDao(Vehicle v){
        if(v instanceof Train){
            return trainDao;
        } else if(v instanceof Car) {
            return carDao;
        } else {
            throw new RuntimeException("unsupported vehicle type");
        }
    }

    void doSomething(Vehicle vehicle){
        VehicleDao dao = getDao(vehicle);
        dao.doSomethind(vehicle);
    }
}
于 2013-03-08T01:32:00.350 に答える