Unlocking Spring: Core Principles, Design Patterns, and IoC Explained
This comprehensive guide walks through Spring's lightweight Java framework, covering its core principles, key features, advantages and drawbacks, the design patterns it employs, core modules, IoC container mechanics, bean scopes, lifecycle, dependency injection techniques, and AOP fundamentals, all illustrated with diagrams and code snippets.
Spring Principles
Spring is a lightweight Java development framework originally created by Rod Johnson to solve coupling problems between business logic and other layers in enterprise applications. It provides a full‑stack, open‑source infrastructure that lets Java developers focus on application code while Spring handles the underlying infrastructure.
Spring offers a one‑stop solution for presentation, business, and persistence layers, yet can seamlessly integrate with other frameworks.
Spring Features
Lightweight : The entire framework can be packaged in a JAR of just over 1 MB, and its runtime overhead is negligible. It is non‑intrusive; objects in a Spring application do not depend on Spring‑specific classes.
Inversion of Control (IoC) : Spring decouples components by injecting dependencies rather than having objects create or locate them themselves.
Aspect‑Oriented Programming (AOP) : Supports AOP to separate business logic from system services.
Container : Manages bean configuration and lifecycle, allowing definition of bean creation, destruction, scope (singleton or prototype), and relationships.
Framework Collection : Combines simple components into complex frameworks, providing declarative composition and many foundational features such as transaction management and persistence integration.
Spring Advantages and Disadvantages
Advantages
Facilitates decoupling and simplifies development by acting as a large factory that manages object creation and dependencies.
Supports AOP for permission interception, monitoring, etc.
Declarative transaction support via configuration.
Easy testing with JUnit4 integration.
Integrates smoothly with popular frameworks (e.g., Struts, Hibernate, MyBatis).
Reduces the difficulty of using complex Java EE APIs (JDBC, JavaMail, RMI) by providing wrappers.
Disadvantages
Relies on reflection, which can affect performance.
Steep learning curve; mastering Spring takes time.
Design Patterns Used in Spring
Spring employs many classic design patterns, including: Proxy – heavily used in AOP and remoting. Singleton – default bean scope; beans defined in configuration are singletons unless specified otherwise. Template Method – used in classes like RestTemplate, JmsTemplate, JpaTemplate to eliminate code duplication. Front Controller – DispatcherServlet dispatches requests. View Helper – JSP tag libraries assist in view composition. Dependency Injection – core concept across BeanFactory and ApplicationContext. Factory Method – BeanFactory creates bean instances.
Core Spring Components
Spring consists of roughly 20 modules comprising over 1,300 files, organized into six major groups: Core Container, AOP, Instrumentation, Data Access/Integration, Web, Messaging, and Test. The diagram below shows the module structure for Spring 5.
spring‑core: Provides basic IoC and DI functionality. spring‑beans: Supplies BeanFactory, a classic factory‑pattern implementation. spring‑context: Builds on spring‑core to offer a framework‑style object access mechanism. spring‑jdbc: Abstracts JDBC, removing boilerplate and vendor‑specific error handling. spring‑aop: Implements aspect‑oriented programming. spring‑web: Integrates web‑specific features such as file upload and servlet‑listener based IoC initialization. spring‑test: Supports unit and integration testing with JUnit or TestNG.
Spring IoC (Inversion of Control)
Concept
IoC transfers control of object creation and wiring from application code to the container, which assembles and manages component lifecycles.
Spring reads bean definitions from configuration files, uses Java reflection to instantiate beans, and establishes dependencies. The IoC container also provides bean caching, lifecycle management, proxy creation, event publishing, and resource loading.
High‑Level View of the Spring Container
When Spring starts, it reads bean configuration, builds a registration table, instantiates beans, wires dependencies, and prepares a ready‑to‑run environment. The bean cache is implemented with a HashMap.
IoC Container Implementation
BeanFactory – Core Infrastructure
BeanFactoryis the foundational infrastructure of Spring, intended for internal use. ApplicationContext is a user‑facing extension of BeanFactory; most applications use ApplicationContext directly.
BeanDefinitionRegistry : Each XML element is represented by a BeanDefinition object describing its configuration; the registry allows manual registration of bean definitions.
BeanFactory Interface : Core method getBean(String name) retrieves a bean; other interfaces extend its capabilities.
ListableBeanFactory : Provides methods to query bean count, names by type, and existence checks.
HierarchicalBeanFactory : Supports parent‑child container hierarchies, enabling web layer beans to access service layer beans while keeping layers isolated.
ConfigurableBeanFactory : Adds customizability such as class loader, property editors, and post‑processors.
AutowireCapableBeanFactory : Performs automatic wiring by name or type.
SingletonBeanRegistry : Caches singleton instances in a HashMap during runtime.
Dependency Logging Framework : Requires a logging framework (e.g., Log4J) during BeanFactory initialization.
ApplicationContext – Developer‑Facing Container
ApplicationContextextends BeanFactory and adds features such as internationalization, resource pattern resolution, event publishing, and lifecycle callbacks.
Key implementations include: ClassPathXmlApplicationContext: Loads configuration from the classpath. FileSystemXmlApplicationContext: Loads configuration from the file system. ApplicationEventPublisher: Publishes context events (startup, shutdown, etc.). MessageSource: Provides i18n message access. ResourcePatternResolver and PathMatchingResourcePatternResolver: Load resources using Ant‑style patterns. Lifecycle: Added in Spring 2.0; start/stop methods manage asynchronous processes, JMX, and scheduling. ConfigurableApplicationContext: Adds refresh() and close() for dynamic reloading and shutdown.
Difference Between BeanFactory and ApplicationContext
Both are core Spring containers; ApplicationContext is a sub‑interface of BeanFactory and provides additional enterprise‑level services.
Dependency Relationships
BeanFactoryhandles bean definitions, loading, instantiation, lifecycle, and dependency management. ApplicationContext inherits those capabilities and adds:
MessageSource for internationalization.
Unified resource access.
Event publishing.
Support for multiple configuration files.
Hierarchical contexts for layered applications (e.g., web layer as child of service layer).
Loading Strategy
BeanFactoryuses lazy loading—beans are created only when getBean() is called, which may delay detection of configuration errors. ApplicationContext eagerly creates all singleton beans at startup, allowing early detection of configuration problems; it pre‑loads singleton beans for faster subsequent access, at the cost of higher memory usage.
Creation and Registration
BeanFactorytypically requires programmatic creation, while ApplicationContext can be declared via configuration files or annotations (e.g., ContextLoader).
Spring Bean Scopes
Spring 3 defines five bean scopes:
singleton : One shared instance per container (default).
prototype : A new instance each time the bean is requested.
request : One instance per HTTP request.
session : One instance per HTTP session.
global session : One instance per global session (used in portlet environments).
Spring Concurrency Handling
Only stateless beans are safe for multi‑threaded use. Most beans can be singletons because Spring uses ThreadLocal to handle non‑thread‑safe state, providing thread safety without requiring developers to write synchronization code. ThreadLocal gives each thread its own copy of a variable, avoiding contention, whereas traditional synchronization uses locks.
Spring Bean Lifecycle
Instantiation
Instantiate the bean (equivalent to new).
IoC Dependency Injection
Spring injects dependencies as defined in the context.
setBeanName
If the bean implements BeanNameAware, Spring calls setBeanName(String) with the bean ID.
BeanFactoryAware
If the bean implements BeanFactoryAware, Spring calls setBeanFactory(BeanFactory).
ApplicationContextAware
If the bean implements ApplicationContextAware, Spring calls setApplicationContext(ApplicationContext).
BeanPostProcessor before initialization
If a BeanPostProcessor is associated, Spring invokes postProcessBeforeInitialization(Object, String).
init‑method
If an init-method is specified, Spring calls it.
BeanPostProcessor after initialization
Spring invokes postProcessAfterInitialization(Object, String) on any BeanPostProcessor.
After these steps the bean is ready for use; if it is a singleton, subsequent getBean calls return the same instance.
Destruction
If the bean implements DisposableBean, Spring calls its destroy() method.
destroy‑method
If a destroy-method is configured, Spring invokes it during container shutdown.
Inner Beans
An inner bean is a bean defined solely for use as a property of another bean; it is usually anonymous and has prototype scope.
Dependency Injection Techniques
Spring supports constructor injection, setter injection, static‑factory injection, and instance‑factory injection. Example code snippets are shown below.
public class CatDaoImpl(String message) { this.message = message; } <bean id="CatDaoImpl" class="com.CatDaoImpl">
<constructor-arg value="message"/>
</bean> public class Id { private int id; public int getId() { return id; } public void setId(int id) { this.id = id; } } <bean id="id" class="com.id">
<property name="id" value="123"/>
</bean>Static Factory Injection
public class DaoFactory { public static final FactoryDao getStaticFactoryDaoImpl() { return new StaticFactoryDaoImpl(); } } public class SpringAction { private FactoryDao staticFactoryDao; public void setStaticFactoryDao(FactoryDao dao) { this.staticFactoryDao = dao; } } <bean name="springAction" class="SpringAction">
<property name="staticFactoryDao" ref="staticFactoryDao"/>
</bean>
<bean name="staticFactoryDao" class="DaoFactory" factory-method="getStaticFactoryDaoImpl"/>Instance Factory Injection
public class DaoFactory { public FactoryDao getFactoryDaoImpl() { return new FactoryDaoImpl(); } } public class SpringAction { private FactoryDao factoryDao; public void setFactoryDao(FactoryDao dao) { this.factoryDao = dao; } } <bean name="springAction" class="SpringAction">
<property name="factoryDao" ref="factoryDao"/>
</bean>
<bean name="daoFactory" class="com.DaoFactory"/>
<bean name="factoryDao" factory-bean="daoFactory" factory-method="getFactoryDaoImpl"/>Five Autowiring Modes
Spring supports manual wiring and five automatic wiring strategies: no: No autowiring; explicit ref is required. byName: Matches bean properties by name. byType: Matches by type; throws an error if multiple candidates exist. constructor: Autowires constructor arguments by type. autodetect: Tries constructor autowiring first, then falls back to byType.
Injecting Java Collections
Spring can configure <list>, <set>, <map>, and <props> elements to inject collections.
<bean id="javaCollection" class="com.howtodoinjava.JavaCollection">
<property name="customList">
<list>
<value>INDIA</value>
<value>Pakistan</value>
<value>USA</value>
<value>UK</value>
</list>
</property>
<property name="customSet">
<set> ... </set>
</property>
<property name="customMap">
<map> ... </map>
</property>
<property name="customProperties">
<props> ... </props>
</property>
</bean>Autowired Annotation Processing
Before using @Autowired, the configuration must include <context:annotation-config/>. Spring registers an AutowiredAnnotationBeanPostProcessor that scans for @Autowired, @Resource, or @Inject and performs type‑based injection (byType). If multiple candidates exist, it falls back to name‑based injection. Setting required=false suppresses exceptions when no bean is found.
Spring AOP
AOP Principles
Object‑Oriented Programming (OOP) handles vertical relationships but struggles with cross‑cutting concerns, leading to code duplication. Aspect‑Oriented Programming (AOP) extracts such concerns (e.g., logging, security, transactions) into reusable modules called aspects, reducing coupling and improving maintainability.
Core AOP Concepts
Aspect : Modularization of a cross‑cutting concern.
Joinpoint : A point during execution (Spring supports method joinpoints).
Pointcut : Predicate that matches joinpoints.
Advice : Action taken at a matched joinpoint (before, after, after‑returning, after‑throwing, around).
Target Object : The object being proxied.
Weaving : Integrating aspects with target objects (compile‑time, load‑time, or runtime).
Introduction : Adding new methods or fields to existing classes without modifying them.
Spring Proxies
Advice + Target Object = Proxy. Spring creates proxies at runtime using either JDK dynamic proxies (interface‑based) or CGLIB (subclass‑based) depending on whether the target class implements interfaces.
Proxy Types
JDK dynamic proxy uses java.lang.reflect.Proxy and InvocationHandler. CGLIB generates subclasses via ASM, allowing proxying of concrete classes.
@Aspect
public class TransactionDemo {
@Pointcut("execution(* com.yangxin.core.service.*.*(..))")
public void point() {}
@Before("point()")
public void before() { System.out.println("transaction begin"); }
@AfterReturning("point()")
public void after() { System.out.println("transaction commit"); }
@Around("point()")
public void around(ProceedingJoinPoint jp) throws Throwable {
System.out.println("transaction begin");
jp.proceed();
System.out.println("transaction commit");
}
}Spring MVC Overview
Spring MVC revolves around DispatcherServlet, which dispatches requests to appropriate controllers, resolves views, and returns the rendered response.
Request → DispatcherServlet : Client request reaches the servlet.
HandlerMapping : DispatcherServlet locates the appropriate controller.
Controller Execution : DispatcherServlet invokes the controller method.
ModelAndView : Controller returns a model and view.
ViewResolver : DispatcherServlet resolves the view and renders the response.
Spring Data & ORM
Spring’s data access modules provide a unified exception hierarchy and transaction support for JDBC, Hibernate, JPA, iBATIS, TopLink, JDO, and OJB. Spring DAO simplifies switching between persistence technologies.
Key JDBC templates include JdbcTemplate, SimpleJdbcTemplate, NamedParameterJdbcTemplate, SimpleJdbcInsert, and SimpleJdbcCall.
Hibernate integration can be achieved via HibernateTemplate with callbacks or by extending HibernateDaoSupport and using AOP‑based transaction interceptors.
Transaction Management
Spring supports both programmatic and declarative transaction management, offering a consistent programming model across JTA, JDBC, Hibernate, JPA, and JDO. Most users prefer declarative transactions for their non‑intrusive nature.
Common Spring Annotations
Component Stereotypes : @Component, @Service, @Repository, @Controller, @RestController.
Dependency Injection : @Autowired (type‑by‑type, optional required=false), @Inject (JSR‑330), @Resource (JSR‑250, name‑by‑default).
Java Configuration : @Configuration, @Bean, @ComponentScan, combined @SpringBootApplication (or custom @WishlyConfiguration).
AOP Annotations : @Aspect, @Pointcut, @Before, @After, @Around, @AfterReturning, @AfterThrowing.
Bean Scope : @Scope("singleton"), @Scope("prototype"), @Scope("request"), @Scope("session"), @Scope("globalSession"), @StepScope (Spring Batch).
Lifecycle : @PostConstruct, @PreDestroy.
Value Injection : @Value supports literals, system properties, SpEL expressions, other bean properties, file resources, URLs, and property files (with @PropertySource and a PropertySourcesPlaceholderConfigurer bean).
Profile & Conditional : @Profile activates beans based on active environment profiles; @Conditional activates beans based on custom conditions.
Async : @EnableAsync + @Async for asynchronous method execution.
Scheduling : @EnableScheduling + @Scheduled (cron, fixedDelay, fixedRate).
Enable Annotations : @EnableAspectJAutoProxy, @EnableWebMvc, @EnableJpaRepositories, @EnableTransactionManagement, @EnableCaching, etc.
Testing Annotations
@RunWith(e.g., SpringJUnit4ClassRunner) and @ContextConfiguration to load application contexts for tests.
Spring MVC Specific Annotations
@Controller– declares a controller class. @RequestMapping – maps URLs to controller methods. @ResponseBody – writes method return value directly to the HTTP response (often JSON). @RequestBody – binds request body to a method parameter. @PathVariable – extracts variables from the URL path. @RestController – combines @Controller and @ResponseBody. @ControllerAdvice – global configuration for controllers (exception handling, data binding, model attributes). @ExceptionHandler, @InitBinder, @ModelAttribute – used within @ControllerAdvice or controllers.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java High-Performance Architecture
Sharing Java development articles and resources, including SSM architecture and the Spring ecosystem (Spring Boot, Spring Cloud, MyBatis, Dubbo, Docker), Zookeeper, Redis, architecture design, microservices, message queues, Git, etc.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
