How do I understand the Spring ApplicationContext?

The Spring ApplicationContext is the central runtime container of a Spring application.

In simple terms:

ApplicationContext is the object that holds your Spring application together.

It knows:

  • which objects Spring should manage
  • how those objects are created
  • how dependencies are injected
  • which configuration values are available
  • which beans need lifecycle callbacks
  • which features like transactions, events, MVC, or JPA are enabled

1. The Short Definition

A Spring ApplicationContext is a container for Spring beans.

A bean is an object managed by Spring.

For example, if you have:

@Service
public class UserService {
}

Spring creates an instance of UserService and stores/manages it inside the ApplicationContext.

Conceptually:

ApplicationContext
 ├── userService
 ├── userRepository
 ├── orderService
 ├── dataSource
 ├── transactionManager
 └── many internal Spring infrastructure beans

2. Why Does Spring Need an ApplicationContext?

Without Spring, you create and connect objects yourself:

UserRepository repository = new UserRepository();
UserService service = new UserService(repository);

With Spring, you describe the objects and dependencies, and Spring does the wiring:

@Service
public class UserService {

    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}
@Repository
public class UserRepository {
}

Spring sees both classes, creates both objects, and injects UserRepository into UserService.

The place where Spring manages all of this is the ApplicationContext.


3. What the ApplicationContext Contains

The ApplicationContext contains two broad categories of things:

Your application beans

Examples:

UserController
UserService
UserRepository
OrderService
PaymentService

These are the objects you usually write.

Spring infrastructure beans

Examples:

DataSource
EntityManagerFactory
TransactionManager
MessageSource
ConversionService
HandlerMapping
BeanPostProcessor

These are objects Spring uses internally to provide features like:

  • dependency injection
  • transactions
  • validation
  • Spring MVC routing
  • database integration
  • event publishing
  • configuration loading

So the context contains both your application and the framework infrastructure around it.


4. What Happens When the ApplicationContext Starts?

When a Spring application starts, Spring creates an ApplicationContext.

A simplified startup flow looks like this:

1. Create the ApplicationContext
2. Read configuration classes, annotations, properties, and component scans
3. Discover bean definitions
4. Decide which beans should exist
5. Create singleton beans
6. Inject dependencies
7. Run bean lifecycle callbacks
8. Apply bean post-processors
9. Create proxies if needed
10. Publish startup events
11. Application is ready

A key detail: Spring first builds bean definitions, then creates actual bean instances.


5. Bean Definition vs. Bean Instance

This distinction helps a lot.

A bean definition is Spring’s recipe for creating a bean.

It includes information like:

Bean name: userService
Bean type: UserService
Scope: singleton
Dependencies: userRepository
Initialization method: maybe present
Lazy or eager: depends on configuration

A bean instance is the actual object created from that recipe.

So conceptually:

Bean definition:
  "I know how to create UserService."

Bean instance:
  new UserService(userRepository)

The ApplicationContext manages both the recipes and the actual objects.


6. Most Beans Are Singletons by Default

By default, Spring creates one shared instance of each bean per ApplicationContext.

That means this:

@Service
public class UserService {
}

usually results in one UserService object shared wherever it is injected.

So if three controllers need UserService, they all receive the same Spring-managed instance.

UserController  ─┐
AdminController ─┼──> same UserService bean
ReportController ┘

This is why Spring service beans should usually be stateless or carefully designed for thread safety.


7. You Usually Do Not Use ApplicationContext Directly

You can ask the context for a bean:

ApplicationContext context = ...;
UserService userService = context.getBean(UserService.class);

But in normal Spring application code, you usually should not do this.

Prefer dependency injection:

@Service
public class ReportService {

    private final UserService userService;

    public ReportService(UserService userService) {
        this.userService = userService;
    }
}

This is better because:

  • dependencies are explicit
  • the class is easier to test
  • the class is not tightly coupled to Spring’s container API
  • Spring can validate dependencies at startup

Use ApplicationContext#getBean() only when you truly need dynamic lookup.


8. ApplicationContext Is More Than a Bean Factory

Spring has a lower-level interface called BeanFactory.

A BeanFactory can create and manage beans.

ApplicationContext extends that idea and adds higher-level application features, such as:

  • event publishing
  • internationalization/message resolution
  • resource loading
  • environment and property access
  • integration with Spring AOP
  • web application support
  • lifecycle management

So you can think of it like this:

BeanFactory:
  Basic bean creation and dependency injection

ApplicationContext:
  BeanFactory + application-level services

In most real applications, you work with ApplicationContext, not directly with BeanFactory.


9. ApplicationContext and Dependency Injection

The most important job of the ApplicationContext is dependency injection.

Given this:

@Service
public class OrderService {

    private final PaymentService paymentService;
    private final OrderRepository orderRepository;

    public OrderService(
            PaymentService paymentService,
            OrderRepository orderRepository
    ) {
        this.paymentService = paymentService;
        this.orderRepository = orderRepository;
    }
}

Spring roughly does this:

1. See that OrderService is a bean
2. See that it needs PaymentService and OrderRepository
3. Find matching beans
4. Create those dependencies if needed
5. Call the OrderService constructor
6. Store the created OrderService bean in the context

You do not manually create the dependency graph. The ApplicationContext does.


10. ApplicationContext and Proxies

Sometimes the object you get from Spring is not the raw object you wrote.

It may be a proxy.

For example:

@Service
public class TransferService {

    @Transactional
    public void transferMoney() {
        // database work
    }
}

When @Transactional is involved, Spring may wrap TransferService in a proxy.

Conceptually:

Caller
  ↓
Transaction proxy
  ↓
Real TransferService

The proxy adds behavior around your method call:

begin transaction
call transferMoney()
commit transaction

or, if there is an error:

rollback transaction

This is why calls between Spring beans often need to go through the Spring-managed object, not through manually created objects.

The ApplicationContext is responsible for creating and managing those proxied beans.


11. ApplicationContext in a Web Application

In a Spring MVC web application, the ApplicationContext also contains web-related infrastructure.

For example:

Controller beans
Handler mappings
Request mappings
Message converters
Validation support
Exception handlers
View resolvers, if using server-side views

When a request arrives, Spring MVC uses beans from the context to decide:

GET /users/42

maps to something like:

@GetMapping("/users/{id}")
public UserDto findUser(@PathVariable Long id) {
    // ...
}

So in a web app, the context is not just managing services and repositories. It also supports request handling.


12. ApplicationContext in Spring Data JPA

With Spring Data JPA, repository interfaces are also managed through the context.

For example:

public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByEmail(String email);
}

You do not create the implementation manually.

Spring Data creates a repository bean and registers it in the ApplicationContext.

Then you can inject it:

@Service
public class UserService {

    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}

The context knows that UserRepository is a Spring-managed bean, even though you did not write the implementation class yourself.


13. Common Types of ApplicationContext

Different application types use different context implementations.

For annotation-based configuration, you may see:

AnnotationConfigApplicationContext

For web applications, Spring uses web-aware contexts.

In Spring Boot, you often do not create the context directly. You usually start the app with:

@SpringBootApplication
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

SpringApplication.run(...) creates and starts the ApplicationContext for you.


14. A Small Manual Example

In a non-Boot or learning example, you might create the context manually:

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {

    public static void main(String[] args) {
        ApplicationContext context =
                new AnnotationConfigApplicationContext(AppConfig.class);

        GreetingService greetingService =
                context.getBean(GreetingService.class);

        System.out.println(greetingService.greet("World"));
    }
}

But in real application classes, prefer injection over calling getBean().


15. Mental Model

A useful mental model is:

ApplicationContext = Spring's runtime registry and factory

It knows:
  - what beans exist
  - how to create them
  - how to connect them
  - how to configure them
  - when to initialize them
  - when to destroy them
  - whether to wrap them in proxies

Your code says:

I need a UserRepository.
I need a PaymentService.
This class is a controller.
This method should be transactional.
This property comes from configuration.

The ApplicationContext says:

I will create those objects,
wire them together,
apply the configuration,
wrap them if needed,
and make the application ready to run.

16. Practical Rules

When working with the ApplicationContext, remember these rules:

  1. Most application objects should be Spring beans.
  2. Use constructor injection for dependencies.
  3. Avoid manually calling new for services, repositories, and controllers.
  4. Avoid frequent direct use of ApplicationContext#getBean().
  5. Keep singleton beans stateless when possible.
  6. Remember that Spring may inject a proxy, not the raw class.
  7. If a bean is missing, check scanning, configuration, profiles, and conditional annotations.
  8. If multiple beans match, use @Primary or @Qualifier.

Bottom Line

The Spring ApplicationContext is the running Spring container.

It is responsible for:

  • discovering beans
  • creating beans
  • injecting dependencies
  • managing lifecycle
  • loading configuration
  • publishing events
  • supporting framework features
  • creating proxies for behavior like transactions

The shortest explanation is:

ApplicationContext is Spring’s runtime container: it creates, stores, wires, configures, and manages the objects that make up your application.

How do I create and manage beans in Spring?

In Spring, a bean is an object managed by the Spring container.

Spring is responsible for:

  • creating the object
  • injecting its dependencies
  • managing its lifecycle
  • applying configuration
  • destroying it when the application shuts down

The container that manages beans is usually the ApplicationContext.


1. What Is a Spring Bean?

A Spring bean is just a normal Java object whose lifecycle is controlled by Spring.

For example:

@Service
public class UserService {

    public String getMessage() {
        return "Hello from UserService";
    }
}

UserService is an ordinary Java class, but because it is annotated with @Service, Spring detects it and manages it as a bean.


2. Common Ways to Create Beans

There are two main ways to create beans in Spring:

  1. Component scanning
  2. Manual bean registration using @Bean

Option 1: Create Beans with Component Scanning

This is the most common approach.

Spring scans your project for classes annotated with stereotypes such as:

@Component
@Service
@Repository
@Controller
@RestController

Example:

@Service
public class EmailService {

    public void sendEmail(String to, String message) {
        System.out.println("Sending email to " + to + ": " + message);
    }
}

Spring automatically creates an EmailService bean.


Common Bean Annotations

@Component

Generic Spring-managed component.

@Component
public class FileStorage {
}

Use this when the class does not fit a more specific role.


@Service

Used for service/business logic classes.

@Service
public class PaymentService {
}

@Repository

Used for data access classes.

@Repository
public class UserRepository {
}

In Spring Data JPA, repositories are often interfaces:

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}

Spring Data JPA creates the implementation automatically.


@Controller

Used for Spring MVC controllers that return views.

@Controller
public class PageController {
}

@RestController

Used for REST APIs.

@RestController
@RequestMapping("/api/users")
public class UserController {
}

@RestController is effectively @Controller plus @ResponseBody.


Option 2: Create Beans Manually with @Bean

Use @Bean when you want to create an object yourself and give it to Spring.

This is common for:

  • third-party classes
  • library objects
  • objects requiring special construction logic
  • configuration-based objects

Example:

@Configuration
public class AppConfig {

    @Bean
    public Clock clock() {
        return Clock.systemUTC();
    }
}

Now Spring manages a Clock bean.

You can inject it elsewhere:

@Service
public class TimeService {

    private final Clock clock;

    public TimeService(Clock clock) {
        this.clock = clock;
    }

    public Instant now() {
        return Instant.now(clock);
    }
}

@Component vs @Bean

Use @Component, @Service, or @Repository when the class is yours and should always be managed by Spring.

Use @Bean when you need explicit construction logic.

Example:

@Configuration
public class HttpClientConfig {

    @Bean
    public HttpClient httpClient() {
        return HttpClient.newBuilder()
                .connectTimeout(Duration.ofSeconds(10))
                .build();
    }
}

Here, HttpClient comes from the JDK, so you cannot annotate it with @Component.


3. Injecting Beans

Once Spring manages a bean, you usually use it through dependency injection.

The recommended style is constructor injection.

@Service
public class OrderService {

    private final PaymentService paymentService;
    private final EmailService emailService;

    public OrderService(PaymentService paymentService, EmailService emailService) {
        this.paymentService = paymentService;
        this.emailService = emailService;
    }

    public void placeOrder() {
        paymentService.charge();
        emailService.sendConfirmation();
    }
}

Spring sees that OrderService needs PaymentService and EmailService, then injects them automatically.


Constructor Injection with Lombok

If your project uses Lombok, you can write:

@Service
@RequiredArgsConstructor
public class OrderService {

    private final PaymentService paymentService;
    private final EmailService emailService;

    public void placeOrder() {
        paymentService.charge();
        emailService.sendConfirmation();
    }
}

@RequiredArgsConstructor generates the constructor for all final fields.

This is common in modern Spring applications.


4. Avoid Field Injection

You may see this style:

@Service
public class OrderService {

    @Autowired
    private PaymentService paymentService;
}

This works, but it is usually discouraged because:

  • it makes testing harder
  • dependencies are hidden
  • fields cannot be final
  • objects can be created in an invalid state

Prefer constructor injection instead.


5. Bean Names

Every bean has a name.

By default, Spring uses the class name with a lowercase-first letter.

@Service
public class PaymentService {
}

Default bean name:

paymentService

You can also give a custom name:

@Service("stripePaymentService")
public class StripePaymentService {
}

Or with @Bean:

@Bean("utcClock")
public Clock clock() {
    return Clock.systemUTC();
}

6. Handling Multiple Beans of the Same Type

If Spring finds multiple beans of the same type, the injection becomes ambiguous.

Example:

public interface PaymentProcessor {
    void process();
}
@Service
public class StripePaymentProcessor implements PaymentProcessor {

    @Override
    public void process() {
        System.out.println("Processing with Stripe");
    }
}
@Service
public class PaypalPaymentProcessor implements PaymentProcessor {

    @Override
    public void process() {
        System.out.println("Processing with PayPal");
    }
}

This is ambiguous:

@Service
public class CheckoutService {

    public CheckoutService(PaymentProcessor paymentProcessor) {
    }
}

Spring does not know which PaymentProcessor to inject.


Use @Primary

Mark one implementation as the default:

@Service
@Primary
public class StripePaymentProcessor implements PaymentProcessor {

    @Override
    public void process() {
        System.out.println("Processing with Stripe");
    }
}

Now Spring injects StripePaymentProcessor unless told otherwise.


Use @Qualifier

Choose a specific bean:

@Service
public class CheckoutService {

    private final PaymentProcessor paymentProcessor;

    public CheckoutService(
            @Qualifier("paypalPaymentProcessor") PaymentProcessor paymentProcessor
    ) {
        this.paymentProcessor = paymentProcessor;
    }
}

The qualifier usually matches the bean name.


7. Bean Scopes

By default, Spring beans are singleton scoped.

That means Spring creates one shared instance per application context.

@Service
public class UserService {
}

This is equivalent to:

@Scope("singleton")
@Service
public class UserService {
}

Common Bean Scopes

singleton

One instance per Spring container.

@Component
@Scope("singleton")
public class AppCache {
}

This is the default.


prototype

A new instance each time the bean is requested.

@Component
@Scope("prototype")
public class ReportBuilder {
}

request

One instance per HTTP request.

@Component
@RequestScope
public class RequestContext {
}

Useful in Spring MVC applications.


session

One instance per HTTP session.

@Component
@SessionScope
public class ShoppingCart {
}

8. Bean Lifecycle

Spring beans go through a lifecycle:

1. Bean definition discovered
2. Object created
3. Dependencies injected
4. Initialization callbacks run
5. Bean is ready to use
6. Destruction callbacks run when context closes

Initialization with @PostConstruct

With Jakarta imports, use:

import jakarta.annotation.PostConstruct;

@Service
public class CacheService {

    @PostConstruct
    public void init() {
        System.out.println("CacheService initialized");
    }
}

Cleanup with @PreDestroy

import jakarta.annotation.PreDestroy;

@Service
public class CacheService {

    @PreDestroy
    public void shutdown() {
        System.out.println("CacheService shutting down");
    }
}

9. Conditional Beans

Sometimes you only want a bean to exist under certain conditions.

In Spring Boot, common annotations include:

@ConditionalOnProperty
@ConditionalOnMissingBean
@ConditionalOnClass
@Profile

Example with profiles:

@Service
@Profile("dev")
public class DevEmailService implements EmailService {
}
@Service
@Profile("prod")
public class SmtpEmailService implements EmailService {
}

Run with:

spring.profiles.active=prod

Then only the prod bean is active.


10. Configuration Properties as Beans

For application configuration, prefer configuration properties instead of manually reading values.

@ConfigurationProperties(prefix = "mail")
public class MailProperties {

    private String host;
    private int port;

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }
}

Enable it:

@Configuration
@EnableConfigurationProperties(MailProperties.class)
public class MailConfig {
}

Example config:

mail.host=smtp.example.com
mail.port=587

Then inject it:

@Service
public class MailService {

    private final MailProperties mailProperties;

    public MailService(MailProperties mailProperties) {
        this.mailProperties = mailProperties;
    }
}

11. Getting Beans Programmatically

Most of the time, you should not call ApplicationContext#getBean() manually.

Prefer this:

@Service
public class ReportService {

    private final CsvExporter csvExporter;

    public ReportService(CsvExporter csvExporter) {
        this.csvExporter = csvExporter;
    }
}

Instead of this:

@Service
public class ReportService {

    private final ApplicationContext applicationContext;

    public ReportService(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    public void export() {
        CsvExporter exporter = applicationContext.getBean(CsvExporter.class);
    }
}

Programmatic lookup is sometimes useful for dynamic behavior, but it should not be your default approach.


12. Dynamic or Lazy Bean Access

If you need lazy or optional access, prefer ObjectProvider.

@Service
public class NotificationService {

    private final ObjectProvider<SmsSender> smsSenderProvider;

    public NotificationService(ObjectProvider<SmsSender> smsSenderProvider) {
        this.smsSenderProvider = smsSenderProvider;
    }

    public void notifyUser(String phoneNumber, String message) {
        SmsSender smsSender = smsSenderProvider.getIfAvailable();

        if (smsSender != null) {
            smsSender.send(phoneNumber, message);
        }
    }
}

This avoids directly depending on ApplicationContext.


13. Lazy Beans

By default, singleton beans are usually created during application startup.

You can make a bean lazy:

@Service
@Lazy
public class ExpensiveService {
}

Or inject it lazily:

@Service
public class DashboardService {

    private final ExpensiveService expensiveService;

    public DashboardService(@Lazy ExpensiveService expensiveService) {
        this.expensiveService = expensiveService;
    }
}

14. Managing Beans in Tests

In Spring tests, beans can be injected into test classes:

@SpringBootTest
class OrderServiceTest {

    @Autowired
    private OrderService orderService;

    @Test
    void placesOrder() {
        orderService.placeOrder();
    }
}

You can replace beans with mocks using Spring Boot testing support:

@SpringBootTest
class OrderServiceTest {

    @MockBean
    private PaymentService paymentService;

    @Autowired
    private OrderService orderService;

    @Test
    void placesOrder() {
        orderService.placeOrder();
    }
}

For plain unit tests, you often do not need Spring:

class OrderServiceTest {

    @Test
    void placesOrder() {
        PaymentService paymentService = mock(PaymentService.class);
        EmailService emailService = mock(EmailService.class);

        OrderService orderService = new OrderService(paymentService, emailService);

        orderService.placeOrder();
    }
}

15. Practical Rules

Use these rules most of the time:

  1. Use @Service for business logic.
  2. Use @Repository for persistence/data access.
  3. Use @Controller or @RestController for web endpoints.
  4. Use @Component for general Spring-managed classes.
  5. Use @Bean for third-party objects or special construction logic.
  6. Prefer constructor injection.
  7. Avoid field injection.
  8. Avoid calling ApplicationContext#getBean() unless you truly need dynamic lookup.
  9. Use @Qualifier or @Primary when multiple beans share the same type.
  10. Keep singleton beans stateless when possible.

Minimal Example

@Service
public class GreetingService {

    public String greet(String name) {
        return "Hello, " + name;
    }
}
@RestController
@RequestMapping("/greetings")
public class GreetingController {

    private final GreetingService greetingService;

    public GreetingController(GreetingService greetingService) {
        this.greetingService = greetingService;
    }

    @GetMapping("/{name}")
    public String greet(@PathVariable String name) {
        return greetingService.greet(name);
    }
}

Spring will:

1. Find GreetingService
2. Create a GreetingService bean
3. Find GreetingController
4. Create a GreetingController bean
5. Inject GreetingService into GreetingController
6. Map GET /greetings/{name}
7. Call the controller method when a request arrives

Bottom Line

To create and manage beans in Spring:

  • annotate your classes with @Component, @Service, @Repository, or @Controller
  • define special beans with @Bean inside @Configuration
  • inject dependencies through constructors
  • let Spring manage lifecycle, scopes, configuration, and wiring

In most cases, you should declare what your application needs and let Spring create and connect the objects for you.

How do I declare a bean in Spring application?

In this example we will learn how to declare a bean in Spring Application. We are going to build a simple Maven project to demonstrate it. So let’s begin by setting up our Maven project.

Creating a Maven Project

Below is the directory structure of our Maven Project.

.
├─ pom.xml
└─ src
   └─ main
      ├─ java
      │  └─ org
      │     └─ kodejava
      │        └─ spring
      │           └─ core
      │              ├─ Hello.java
      │              ├─ HelloImpl.java
      │              └─ HelloWorldDemo.java
      └─ resources
         └─ spring.xml

Configuring Maven pom.xml File

We need to create a pom.xml file and add our project configuration and library dependency.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>kodejava-example</artifactId>
        <groupId>org.kodejava</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>kodejava-springframework-core</artifactId>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.3.23</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.3.23</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>5.3.23</version>
        </dependency>
    </dependencies>
</project>

Creating a Bean

Next we will create a simple bean called HelloImpl. This bean implements an interface called Hello with a single method sayHello() to be implemented. Here is the interface it’s implementation definition.

package org.kodejava.spring.core;

public interface Hello {
    void sayHello();
}
package org.kodejava.spring.core;

public class HelloImpl implements Hello {

    public void sayHello() {
        System.out.println("Hello World!");
    }
}

Register the Bean in Spring Configuration

After having the bean we need to create the Spring configuration, which is an xml file, and we named it spring.xml. The bean declared using the bean element in the configuration file. At minimum the declaration contains the bean’s id and it’s class.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="hello" class="org.kodejava.spring.core.HelloImpl" />

</beans>

Use the Bean in Our Application

Now we have the bean declared in the Spring container. The next step show you how to get the bean from the container and use it in our program. There are many ways that can be used to load the Spring container. Here we will use the ClassPathXmlApplicationContext. This class load the configuration that found in the runtime classpath.

package org.kodejava.spring.core;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class HelloWorldDemo {
    public static void main(String[] args) {
        String config = "spring.xml";
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(config);

        Hello hello = (Hello) context.getBean("hello");
        hello.sayHello();
        context.close();
    }
}