복붙노트

[SPRING] Spring 3 - 다른 객체 속성을 기반으로 런타임에 동적 Autowiring

SPRING

Spring 3 - 다른 객체 속성을 기반으로 런타임에 동적 Autowiring

저는 Spring 3.1 MVC 어플리케이션을 작업하고 있습니다. 시나리오 중 하나에 대해 DAO의 두 가지 구현을 작성해야했습니다. 나는 이것을 서비스 레이어에서 autowire하는 법을 알고 싶다.  다른 객체의 속성을 기반으로합니다.

예를 들어,

    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 주석 중 하나를 사용하고 싶었지만 두 속성 모두 일부 속성을 기반으로 조회하는 데 제한이 있습니다. 다른 개체의 속성을 기반으로 런타임에이 작업을 수행하는 방법을 잘 모르겠습니다.

해결법

  1. ==============================

    1.내 솔루션은 다음과 같습니다 :

    내 솔루션은 다음과 같습니다 :

    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 구현 목록을 autowire합니다.

    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 구현을 추가하기 만하면됩니다.

  2. ==============================

    2.이 전략을 수행하기위한 더 깨끗한 옵션이 있습니다. 우리는 Spring이 제어 할 수있는 bean을 어디서나 주입 할 수있을 정도로 똑똑하다는 것을 알고 있으므로 @Autowire 또는 @Resource 주석으로 VehicleDAO를 볼 때 그 구현을 정확하게 주입 할 것입니다.

    이 전략을 수행하기위한 더 깨끗한 옵션이 있습니다. 우리는 Spring이 제어 할 수있는 bean을 어디서나 주입 할 수있을 정도로 똑똑하다는 것을 알고 있으므로 @Autowire 또는 @Resource 주석으로 VehicleDAO를 볼 때 그 구현을 정확하게 주입 할 것입니다.

    이 점을 염두에두면 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();
    ...
    
  3. ==============================

    3.Vehicle은 @Model이기 때문에 런타임 값이므로 autowiring 값에 Vehicle을 사용할 수 없습니다.

    Vehicle은 @Model이기 때문에 런타임 값이므로 autowiring 값에 Vehicle을 사용할 수 없습니다.

    차량은 인수로서 서비스 메소드에 전달되어야합니다.

    공용 인터페이스 VehicleService {     void doSomething (차량 차량); }

    CarDao와 TrainDAO가 동일한 VehicleDao 서비스를 구현한다고 가정 할 때, 다른 말로는별로 의미가 없을 것입니다.

    따라서 VehicleServiceImpl에서 getVehicleDao (Vehicle v) {}와 같은 메소드를 작성하여 dao의 올바른 인스턴스를 얻을 것을 권장합니다.

    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);
        }
    }
    
  4. ==============================

    4.한 가지 유의하십시오 : 이전 솔루션은 훌륭하고 간단하지만 봄마다 각 빈의 인스턴스가 만들어집니다.

    한 가지 유의하십시오 : 이전 솔루션은 훌륭하고 간단하지만 봄마다 각 빈의 인스턴스가 만들어집니다.

    그래서 내 솔루션 인터페이스 대신 추상 클래스 VehicleService를 만드는 것입니다

    그런 다음 appContext에서

    @Bean
    @Primary
    VehicleService paymentProviderService()
    {
        return ...new (your requested instance by your own)...
    }
    
  5. from https://stackoverflow.com/questions/15284851/spring-3-dynamic-autowiring-at-runtime-based-on-another-object-attribute by cc-by-sa and MIT license