Razlika između BeanFactory i ApplicationContext
1. Pregled
Spring Framework dolazi s dva kontejnera IOC - BeanFactory i ApplicationContext. The BeanFactory je najosnovnija verzija kontejnera IOC, a ApplicationContext proširuje značajke BeanFactory.
U ovom brzom vodiču razumjet ćemo značajne razlike između ova dva kontejnera MOK-a praktičnim primjerima.
2. Lijeno utovar nasuprot željnom učitavanju
BeanFactory utovari grah na zahtjev, dok ApplicationContext učitava sve mahune pri pokretanju. Tako, BeanFactory je lagan u odnosu na ApplicationContext. Shvatimo to na primjeru.
2.1. Lijeno učitavanje sa BeanFactory
Pretpostavimo da imamo jedinstvenu klasu zrna graha Student jednom metodom:
javni razred Student {javni statički logički isBeanInstantiated = false; javna void postConstruct () {setBeanInstantiated (true); } // standardni postavljači i dobivači}
Mi ćemo definirati postConstruct () metoda kao init-metoda u našem BeanFactory konfiguracijska datoteka, ioc-container-razlika-primjer.xml:
Sada, napišite test koji stvara a BeanFactory da provjeri učitava li Student grah:
@Test public void whenBFInitialized_thenStudentNotInitialized () {Resurs res = new ClassPathResource ("ioc-container-razlika-example.xml"); Tvornica BeanFactory = novi XmlBeanFactory (res); assertFalse (Student.isBeanInstantiated ()); }
Ovdje, the Student objekt nije inicijaliziran. Drugim riječima, samo BeanFactory je inicijaliziran. Grah definiran u našem BeanFactory će se učitati samo kada izričito pozovemo getBean () metoda.
Provjerimo inicijalizaciju našeg Student grah gdje ručno zovemo getBean () metoda:
@Test public void whenBFInitialized_thenStudentInitialized () {Resurs res = new ClassPathResource ("ioc-container-razlika-example.xml"); Tvornica BeanFactory = novi XmlBeanFactory (res); Student student = (Student) factory.getBean ("student"); assertTrue (Student.isBeanInstantiated ()); }
Evo, Student grah se uspješno učitava. Dakle, BeanFactory grah učitava samo kada je to potrebno.
2.2. Željno učitavanje sa ApplicationContext
Sada, iskoristimo ApplicationContext na mjestu BeanFactory.
Mi ćemo samo definirati ApplicationContext, i odmah će učitati sav grah koristeći strategiju nestrpljivog utovara:
@Test public void whenAppContInitialized_thenStudentInitialized () {ApplicationContext context = new ClassPathXmlApplicationContext ("ioc-container-razlika-example.xml"); assertTrue (Student.isBeanInstantiated ()); }
Evo, Student objekt je stvoren iako nismo pozvali getBean () metoda.
ApplicationContext smatra se teškim kontejnerom IOC-a jer njegova strategija nestrpljivog utovara učitava sve grah prilikom pokretanja. BeanFactory lagan je u usporedbi i mogao bi biti koristan u memorijski ograničenim sustavima. Štoviše, vidjet ćemo u sljedećim odjeljcima zašto ApplicationContext je poželjna za većinu slučajeva korištenja.
3. Značajke poslovne aplikacije
ApplicationContext pojačava BeanFactory u više okvirno orijentiranom stilu i pruža nekoliko značajki koje su prikladne za poslovne aplikacije.
Na primjer, to pruža razmjenu poruka (i18n ili internacionalizacija) funkcionalnost, objavljivanje događaja funkcionalnost, injekcija ovisnosti zasnovana na bilješkama, i laka integracija sa značajkama Spring AOP. Osim ovoga, ApplicationContext podržava gotovo sve vrste opsega graha, ali BeanFactory podržava samo dva opsega - Singleton i Prototip. Stoga je uvijek poželjno koristiti ApplicationContext prilikom izrade složenih poslovnih aplikacija. The ApplicationContext automatski se registrira BeanFactoryPostProcessor i BeanPostProcessor pri pokretanju. S druge strane, BeanFactory ne registrira ta sučelja automatski. Da bismo razumjeli, napišimo dva razreda. Prvo, imamo CustomBeanFactoryPostProcessor klase koja provodi BeanFactoryPostProcessor: Evo, nadjačali smo postProcessBeanFactory () način provjere njegove registracije. Drugo, imamo još jedan razred, CustomBeanPostProcessor, koji provodi BeanPostProcessor: Evo, nadjačali smo postProcessBeforeInitialization () način provjere njegove registracije. Također, konfigurirali smo obje klase u našem ioc-container-razlika-primjer.xml konfiguracijska datoteka: Pogledajmo test slučaja kako bismo provjerili jesu li ove dvije klase automatski registrirane tijekom pokretanja: Kao što možemo vidjeti iz našeg testa, automatska registracija se nije dogodila. Sada, pogledajmo test koji ih ručno dodaje u BeanFactory: Ovdje smo koristili postProcessBeanFactory () metoda za registraciju CustomBeanFactoryPostProcessor i addBeanPostProcessor () metoda za registraciju CustomBeanPostProcessor. Oboje su se uspješno registrirali u ovom slučaju. Kao što smo ranije primijetili, ApplicationContext automatski registrira obje klase bez pisanja dodatnog koda. Provjerimo ovo ponašanje u jediničnom testu: Kao što vidimo, automatska registracija obje klase je uspješna u ovom slučaju. Stoga, uvijek je preporučljivo koristiti ApplicationContext jer Spring 2.0 (i noviji) intenzivno koristi BeanPostProcessor. To je također vrijedno napomenuti ako se koristite ravnicom BeanFactory, tada značajke poput transakcija i AOP-a neće stupiti na snagu (barem ne bez pisanja dodatnih redaka koda). To može dovesti do zabune jer ništa neće izgledati pogrešno s konfiguracijom. U ovom smo članku vidjeli ključne razlike između ApplicationContext i BeanFactory s praktičnim primjerima. The ApplicationContext dolazi s naprednim značajkama, uključujući nekoliko koje su usmjerene na poslovne programe, dok BeanFactory dolazi sa samo osnovnim značajkama. Stoga se općenito preporučuje korištenje ApplicationContext, i trebali bismo koristiti BeanFactory samo kada je potrošnja memorije kritična. Kao i uvijek, kôd članka dostupan je na GitHub-u.4. Automatska registracija BeanFactoryPostProcessor i BeanPostProcessor
4.1. Registracija u BeanFactory
javna klasa CustomBeanFactoryPostProcessor implementira BeanFactoryPostProcessor {private static boolean isBeanFactoryPostProcessorRegistered = false; @Override public void postProcessBeanFactory (ConfigurableListableBeanFactory beanFactory) {setBeanFactoryPostProcessorRegistered (true); } // standardni postavljači i dobivači}
javna klasa CustomBeanPostProcessor implementira BeanPostProcessor {private static boolean isBeanPostProcessorRegistered = false; @Override public Object postProcessBeforeInitialization (Object bean, String beanName) {setBeanPostProcessorRegistered (true); grah za povratak; } // standardni postavljači i dobivači}
@Test public void whenBFInitialized_thenBFPProcessorAndBPProcessorNotRegAutomatically () {Resurs res = new ClassPathResource ("ioc-container-razlika-example.xml"); ConfigurableListableBeanFactory tvornica = nova XmlBeanFactory (res); assertFalse (CustomBeanFactoryPostProcessor.isBeanFactoryPostProcessorRegistered ()); assertFalse (CustomBeanPostProcessor.isBeanPostProcessorRegistered ()); }
@Test public void whenBFPostProcessorAndBPProcessorRegisteredManually_thenReturnTrue () {Resurs res = novi ClassPathResource ("ioc-container-razlika-example.xml"); ConfigurableListableBeanFactory tvornica = nova XmlBeanFactory (res); CustomBeanFactoryPostProcessor beanFactoryPostProcessor = novi CustomBeanFactoryPostProcessor (); beanFactoryPostProcessor.postProcessBeanFactory (tvornica); assertTrue (CustomBeanFactoryPostProcessor.isBeanFactoryPostProcessorRegistered ()); CustomBeanPostProcessor beanPostProcessor = novi CustomBeanPostProcessor (); factory.addBeanPostProcessor (beanPostProcessor); Student student = (Student) factory.getBean ("student"); assertTrue (CustomBeanPostProcessor.isBeanPostProcessorRegistered ()); }
4.2. Registracija u ApplicationContext
@Test public void whenAppContInitialized_thenBFPostProcessorAndBPostProcessorRegisteredAutomatically () {ApplicationContext context = new ClassPathXmlApplicationContext ("ioc-container-razlika-example.xml"); assertTrue (CustomBeanFactoryPostProcessor.isBeanFactoryPostProcessorRegistered ()); assertTrue (CustomBeanPostProcessor.isBeanPostProcessorRegistered ()); }
5. Zaključak