BeanFactory与ApplicationContext差异解析:附代码示例需求
Hey there! I totally get wanting to dig into the nitty-gritty differences even if you know ApplicationContext is the better choice for production. Let's walk through code examples for both the internationalization and event publishing gaps between BeanFactory and ApplicationContext to make this concrete.
1. Internationalization (i18n) Support
BeanFactory doesn't have built-in support for resolving localized messages—you'd have to manually register and wire a MessageSource bean to get this working. ApplicationContext, on the other hand, automatically detects and uses a MessageSource bean (named messageSource by default) out of the box.
Step 1: Create Localization Resource Files
First, add these two property files to your src/main/resources folder:
messages_en.properties:greeting=Hello, {0}!messages_zh.properties:greeting=你好, {0}!
Step 2: Test with BeanFactory
import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.context.support.ResourceBundleMessageSource; import org.springframework.core.io.ClassPathResource; public class BeanFactoryI18nTest { public static void main(String[] args) { // Basic BeanFactory initialization BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("beans.xml")); // BeanFactory doesn't auto-detect MessageSource—we have to create and configure it manually ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); messageSource.setBasename("messages"); // Now we can resolve messages, but this isn't integrated with the BeanFactory itself String englishGreeting = messageSource.getMessage("greeting", new Object[]{"Alice"}, null); String chineseGreeting = messageSource.getMessage("greeting", new Object[]{"爱丽丝"}, java.util.Locale.CHINA); System.out.println("English (BeanFactory): " + englishGreeting); System.out.println("Chinese (BeanFactory): " + chineseGreeting); } }
Note: The BeanFactory itself doesn't provide access to the MessageSource—you're just creating a standalone instance here. There's no way to inject this MessageSource into other beans via BeanFactory without explicit wiring.
Step 3: Test with ApplicationContext
import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class ApplicationContextI18nTest { public static void main(String[] args) { // ApplicationContext automatically loads the MessageSource ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); // Directly resolve messages using the context's built-in i18n support String englishGreeting = context.getMessage("greeting", new Object[]{"Alice"}, null); String chineseGreeting = context.getMessage("greeting", new Object[]{"爱丽丝"}, java.util.Locale.CHINA); System.out.println("English (ApplicationContext): " + englishGreeting); System.out.println("Chinese (ApplicationContext): " + chineseGreeting); } }
Here, the ApplicationContext natively implements the
MessageSourceinterface, so you can callgetMessage()directly on it. Plus, any bean in the context can have aMessageSourceinjected automatically.
2. Event Publishing & Listener Support
BeanFactory lacks a built-in event multicaster, so publishing events to registered listeners requires manual setup. ApplicationContext comes with an ApplicationEventMulticaster that automatically detects ApplicationListener beans and broadcasts events to them.
Step 1: Create a Custom Event and Listener
import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; // Custom event class UserRegisteredEvent extends ApplicationEvent { private String username; public UserRegisteredEvent(Object source, String username) { super(source); this.username = username; } public String getUsername() { return username; } } // Custom listener class UserRegistrationListener implements ApplicationListener<UserRegisteredEvent> { @Override public void onApplicationEvent(UserRegisteredEvent event) { System.out.println("Listener notified: User " + event.getUsername() + " has registered!"); } }
Step 2: Test with BeanFactory
import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.context.event.SimpleApplicationEventMulticaster; import org.springframework.core.io.ClassPathResource; public class BeanFactoryEventTest { public static void main(String[] args) { BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("beans.xml")); // BeanFactory doesn't have an event multicaster by default—we need to create one SimpleApplicationEventMulticaster eventMulticaster = new SimpleApplicationEventMulticaster(); // Register our listener manually eventMulticaster.addApplicationListener(new UserRegistrationListener()); // Publish the event (we have to trigger this manually) eventMulticaster.multicastEvent(new UserRegisteredEvent(beanFactory, "Bob")); } }
Notice how we have to manually create the event multicaster, register the listener, and publish the event. There's no automatic detection of listeners in the BeanFactory, and beans can't easily subscribe to events without this manual setup.
Step 3: Test with ApplicationContext
import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class ApplicationContextEventTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); // Register the listener (or define it in beans.xml—ApplicationContext will detect it automatically) context.addApplicationListener(new UserRegistrationListener()); // Publish the event—ApplicationContext handles the multicasting context.publishEvent(new UserRegisteredEvent(context, "Bob")); } }
Here, the ApplicationContext takes care of the event multicaster behind the scenes. If you define the
UserRegistrationListeneras a bean in yourbeans.xml, the context will automatically detect and register it without you having to calladdApplicationListener(). Publishing events is as simple as callingpublishEvent().
Quick Recap
- Internationalization: BeanFactory requires manual setup of
MessageSourceand doesn't integrate it into the container; ApplicationContext natively supports i18n and auto-detectsMessageSourcebeans. - Event Publishing: BeanFactory needs manual configuration of an event multicaster and listener registration; ApplicationContext has built-in event handling, auto-detects listeners, and simplifies event publishing.
Even though ApplicationContext is clearly more feature-complete, seeing these examples helps understand why it's the preferred choice—and what BeanFactory is missing under the hood.
内容的提问来源于stack exchange,提问作者pjj

