SORU
11 Kasım 2013, PAZARTESİ


Neden benim Bahar @Autowired alan boş mu?

Not: Bu ortak bir sorun için standart bir cevap olacak şekilde tasarlanmıştır.

@Autowired Alanı (rateService) @Service Bahar sınıfı (MileageFeeCalculator) var, ama bu alanı kullanmaya çalıştığımda null. Günlükleri göstermek hem MileageFeeCalculator fasulye ve MileageRateService çekirdeği oluşturulan, ama ben bir NullPointerException zaman ben denemek için çağrı mileageCharge yöntem benim hizmet bean. Neden Bahar alan autowiring değil mi?

Denetçi sınıfı:

@Controller
public class MileageFeeController {    
    @RequestMapping("/mileage/{miles}")
    @ResponseBody
    public float mileageFee(@PathVariable int miles) {
        MileageFeeCalculator calc = new MileageFeeCalculator();
        return calc.mileageCharge(miles);
    }
}

Hizmet sınıfı:

@Service
public class MileageFeeCalculator {

    @Autowired
    private MileageRateService rateService; // <--- should be autowired, is null

    public float mileageCharge(final int miles) {
        return (miles * rateService.ratePerMile()); // <--- throws NPE
    }
}

MileageFeeCalculator ama autowired bir hizmet bean değil mi:

@Service
public class MileageRateService {
    public float ratePerMile() {
        return 0.565f;
    }
}

GET /mileage/3 çalıştığımda bu özel durum alıyorum:

java.lang.NullPointerException: null
    at com.chrylis.example.spring_autowired_npe.MileageFeeCalculator.mileageCharge(MileageFeeCalculator.java:13)
    at com.chrylis.example.spring_autowired_npe.MileageFeeController.mileageFee(MileageFeeController.java:14)
    ...

CEVAP
11 Kasım 2013, PAZARTESİ


Alanı @Autowired Bahar new ile ve bilmiyordu bunu autowire için oluşturduğunuz MileageFeeCalculator kopyasını haberi yok çünkü null açıklamalı.

The Spring Inversion of Control (IoC) container üç ana mantıksal bileşenler: bir kayıt (ApplicationContext) bileşenleri (fasulye), mevcut tarafından kullanılmak üzere bir uygulama, bir configurer sistem enjekte nesne bağımlılıkları onları ile eşleşen bağımlılıkları ile fasulye bağlamında, ve bir bağımlılık çözücü o olabilir bak bir yapılandırma çok farklı fasulye ve nasıl belirlemek için oluşturmak ve yapılandırmak onlara gerekli emri.

IoC konteyner büyü değil, ve bir şekilde onlara bildirmek sürece Java nesneler hakkında bilmenin bir yolu vardır. JVM yeni nesnesinin bir kopyasını oluşturur ve doğruca sana eller new,--aradığınızda, hiç yapılandırma sürecinden geçer. Fasulyenin yapılandırılmış alabilirsiniz üç yolu vardır.

Bu kod, Bahar Boot, this GitHub project; her yaklaşım için tam çalışan bir proje çalışması için gereken her şeyi görebilirsiniz saldırmaya kullanarak attılar.NullPointerExceptionile etiketi: nonworking

Fasulyenin enjekte

En çok tercih edilen seçenek Bahar fasulye tüm autowire izin vermektir; bu kodu en az miktarda gerektirir ve en sürdürülebilir. İstediğin gibi autowiring iş yapmak için de böyle MileageFeeCalculator autowire:

@Controller
public class MileageFeeController {

    @Autowired
    private MileageFeeCalculator calc;

    @RequestMapping("/mileage/{miles}")
    @ResponseBody
    public float mileageFee(@PathVariable int miles) {
        return calc.mileageCharge(miles);
    }
}

Eğer farklı istekleri için servis nesnenin yeni bir örneğini oluşturmak için ihtiyacınız varsa, hala the Spring bean scopes kullanarak enjeksiyon kullanabilirsiniz.

@MileageFeeCalculator servis nesne enjekte ederek çalışır etiketi: working-inject-bean

@Yapılandırılabilir Kullanın

Eğer gerçekten nesneleri new ile autowired için oluşturulan gerekiyorsa, 53 ** nesneleri enjekte edebilirsiniz. Bu Bahar yeni bir örneğini yapılandırmak böylece yaratılan bu Bahar uyarıları bu kod bloğu içine ekler kod yaklaşım. Bu (ajc ile derleme gibi) ve Bahar zamanı yapılandırma işleyicileri (@EnableSpringConfigured JavaConfig sözdizimi ile) inşa dönüm yapılandırma biraz gerektirir. Bu yaklaşım, varlıkların new örnekleri kalıcılık gerekli bilgileri enjekte almak için izin Roo Aktif Kayıt Sistemi tarafından kullanılır.

@Service
@Configurable
public class MileageFeeCalculator {

    @Autowired
    private MileageRateService rateService;

    public float mileageCharge(final int miles) {
        return (miles * rateService.ratePerMile());
    }
}

Hizmet nesnesi @Configurable kullanarak çalışan etiket: working-configurable

Manuel bean arama: tavsiye edilmez

Bu yaklaşım, özel durumlarda eski kod ile arayüz için uygundur. Her zaman tercih Bahar ve eski kod çağırabilir, ama doğrudan bir fasulye için Bahar uygulama bağlamında sormak mümkündür autowire bu adaptörü singleton bir sınıf oluşturmak için dolmak üzere.

Bunu yapmak için, Bahar ApplicationContext nesneye bir referans verebilir bir sınıf gerekir:

@Component
public class ApplicationContextHolder implements ApplicationContextAware {
    private static ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;   
    }

    public static ApplicationContext getContext() {
        return context;
    }
}

Sonra eski kodunuzu getContext() arama ve ihtiyacı olan fasulye almak

@Controller
public class MileageFeeController {    
    @RequestMapping("/mileage/{miles}")
    @ResponseBody
    public float mileageFee(@PathVariable int miles) {
        MileageFeeCalculator calc = ApplicationContextHolder.getContext().getBean(MileageFeeCalculator.class);
        return calc.mileageCharge(miles);
    }
}

Elle İlkbahar bağlamında hizmet nesne bakarak çalışan etiket: working-manual-lookup

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • dirkgently1

    dirkgently1

    13 NİSAN 2006
  • kndx

    kndx

    11 Mart 2006
  • TheTwistedFrequency

    TheTwistedFr

    26 NİSAN 2010