Spring Framework Core - IoC Container and Dependency Injection
—
This section covers the fundamental Spring Core infrastructure APIs that provide the building blocks for dependency injection, component ordering, type resolution, and basic utilities.
Spring provides a comprehensive ordering system for components that need to be sorted by priority.
Basic Ordering Interface
public interface Ordered {
int HIGHEST_PRECEDENCE = Integer.MIN_VALUE;
int LOWEST_PRECEDENCE = Integer.MAX_VALUE;
int getOrder();
}
public interface PriorityOrdered extends Ordered {
// Marker interface for high-priority ordered objects
}Usage Examples
// Implement ordered components
public class DatabaseMigration implements Ordered {
@Override
public int getOrder() {
return 1; // High priority (low number)
}
}
public class CacheInitializer implements PriorityOrdered {
@Override
public int getOrder() {
return 0; // Even higher priority
}
}
// Use ordering comparator
List<Ordered> components = Arrays.asList(
new DatabaseMigration(),
new CacheInitializer()
);
OrderComparator.sort(components);Order Comparator
public class OrderComparator implements Comparator<Object> {
public static final OrderComparator INSTANCE = new OrderComparator();
public static void sort(List<?> list);
public static void sort(Object[] array);
@Override
public int compare(Object o1, Object o2);
protected int getOrder(Object obj);
}Spring provides advanced type resolution capabilities for working with generic types and method parameters.
ResolvableType API
public final class ResolvableType {
// Static factory methods
public static ResolvableType forField(Field field);
public static ResolvableType forMethodParameter(Method method, int parameterIndex);
public static ResolvableType forMethodParameter(MethodParameter methodParameter);
public static ResolvableType forMethodReturnType(Method method);
public static ResolvableType forClass(Class<?> clazz);
public static ResolvableType forClassWithGenerics(Class<?> clazz, Class<?>... generics);
public static ResolvableType forClassWithGenerics(Class<?> clazz, ResolvableType... generics);
public static ResolvableType forType(Type type);
public static ResolvableType forInstance(Object instance);
// Resolution methods
public Class<?> resolve();
public Class<?> resolve(Class<?> fallback);
public Class<?> toClass();
public Type getType();
public Class<?> getRawClass();
public Object getSource();
// Type hierarchy navigation
public ResolvableType getSuperType();
public ResolvableType[] getInterfaces();
public ResolvableType as(Class<?> type);
// Generic type access
public ResolvableType getGeneric(int... indexes);
public ResolvableType[] getGenerics();
public Class<?>[] resolveGenerics();
public Class<?>[] resolveGenerics(Class<?> fallback);
// Type checking
public boolean hasGenerics();
public boolean hasUnresolvableGenerics();
public boolean isAssignableFrom(Class<?> other);
public boolean isAssignableFrom(ResolvableType other);
public boolean isArray();
public boolean isInstance(Object obj);
}Usage Examples
// Resolve generic types from fields
public class GenericService<T, U> {
private List<T> items;
private Map<String, U> cache;
}
Field itemsField = GenericService.class.getDeclaredField("items");
ResolvableType fieldType = ResolvableType.forField(itemsField);
ResolvableType genericType = fieldType.getGeneric(0); // Gets T
// Resolve method parameter types
public void processItems(List<String> items, Map<Long, User> userMap) { }
Method method = MyClass.class.getMethod("processItems", List.class, Map.class);
ResolvableType listParam = ResolvableType.forMethodParameter(method, 0);
ResolvableType stringType = listParam.getGeneric(0); // String.class
ResolvableType mapParam = ResolvableType.forMethodParameter(method, 1);
ResolvableType keyType = mapParam.getGeneric(0); // Long.class
ResolvableType valueType = mapParam.getGeneric(1); // User.class
// Create types programmatically
ResolvableType stringListType = ResolvableType.forClassWithGenerics(List.class, String.class);
ResolvableType mapType = ResolvableType.forClassWithGenerics(
Map.class,
ResolvableType.forClass(String.class),
ResolvableType.forClass(Integer.class)
);MethodParameter API
public class MethodParameter {
// Constructors
public MethodParameter(Method method, int parameterIndex);
public MethodParameter(Constructor<?> constructor, int parameterIndex);
public MethodParameter(MethodParameter original);
// Parameter info
public Method getMethod();
public Constructor<?> getConstructor();
public Class<?> getDeclaringClass();
public Member getMember();
public AnnotatedElement getAnnotatedElement();
// Type information
public Class<?> getParameterType();
public Type getGenericParameterType();
public ResolvableType getResolvableType();
public int getParameterIndex();
// Annotations
public Annotation[] getParameterAnnotations();
public <A extends Annotation> A getParameterAnnotation(Class<A> annotationType);
public boolean hasParameterAnnotation(Class<? extends Annotation> annotationType);
// Parameter names and attributes
public String getParameterName();
public boolean isOptional();
public MethodParameter nested();
public MethodParameter nested(int nestingLevel);
public MethodParameter withTypeIndex(int typeIndex);
// Utility methods
public MethodParameter clone();
public void initParameterNameDiscovery(ParameterNameDiscoverer parameterNameDiscoverer);
}Usage Examples
// Analyze method parameters
public void handleRequest(@RequestParam String name,
@RequestBody Optional<User> user,
HttpServletRequest request) { }
Method method = MyController.class.getMethod("handleRequest",
String.class, Optional.class, HttpServletRequest.class);
// Inspect first parameter
MethodParameter nameParam = new MethodParameter(method, 0);
Class<?> paramType = nameParam.getParameterType(); // String.class
RequestParam annotation = nameParam.getParameterAnnotation(RequestParam.class);
// Inspect optional parameter
MethodParameter userParam = new MethodParameter(method, 1);
boolean isOptional = userParam.isOptional(); // true
MethodParameter nestedParam = userParam.nested(); // Gets Optional<User> -> User
Class<?> nestedType = nestedParam.getParameterType(); // User.classSpring provides alias management for component names and identifiers.
AliasRegistry Interface
public interface AliasRegistry {
void registerAlias(String name, String alias);
void removeAlias(String alias);
boolean isAlias(String name);
String[] getAliases(String name);
}
public class SimpleAliasRegistry implements AliasRegistry, BeanNameAware {
public SimpleAliasRegistry();
@Override
public void registerAlias(String name, String alias);
@Override
public void removeAlias(String alias);
@Override
public boolean isAlias(String name);
@Override
public String[] getAliases(String name);
public String canonicalName(String name);
public boolean hasAlias(String name, String alias);
public void resolveAliases(StringValueResolver valueResolver);
}Usage Examples
// Register and use aliases
AliasRegistry registry = new SimpleAliasRegistry();
// Register aliases
registry.registerAlias("dataSource", "db");
registry.registerAlias("dataSource", "database");
registry.registerAlias("userService", "users");
// Check aliases
boolean isAlias = registry.isAlias("db"); // true
String[] aliases = registry.getAliases("dataSource"); // ["db", "database"]
// Remove aliases
registry.removeAlias("db");Spring provides a system for attaching arbitrary metadata to objects.
AttributeAccessor Interface
public interface AttributeAccessor {
void setAttribute(String name, Object value);
Object getAttribute(String name);
Object removeAttribute(String name);
boolean hasAttribute(String name);
String[] attributeNames();
}
public class AttributeAccessorSupport implements AttributeAccessor, Serializable {
public AttributeAccessorSupport();
@Override
public void setAttribute(String name, Object value);
@Override
public Object getAttribute(String name);
@Override
public Object removeAttribute(String name);
@Override
public boolean hasAttribute(String name);
@Override
public String[] attributeNames();
protected void copyAttributesFrom(AttributeAccessor source);
}Usage Examples
// Attach metadata to objects
AttributeAccessor accessor = new AttributeAccessorSupport();
// Set attributes
accessor.setAttribute("created", Instant.now());
accessor.setAttribute("author", "john.doe");
accessor.setAttribute("version", "1.0");
// Get attributes
Instant created = (Instant) accessor.getAttribute("created");
String author = (String) accessor.getAttribute("author");
// Check and remove
if (accessor.hasAttribute("version")) {
Object version = accessor.removeAttribute("version");
}
// List all attributes
String[] names = accessor.attributeNames();Spring provides base classes for nested exception handling with root cause tracking.
Nested Exception Classes
public abstract class NestedRuntimeException extends RuntimeException {
public NestedRuntimeException(String msg);
public NestedRuntimeException(String msg, Throwable cause);
public String getMessage();
public Throwable getRootCause();
public Throwable getMostSpecificCause();
public boolean contains(Class<?> exType);
public static String buildMessage(String message, Throwable cause);
}
public abstract class NestedCheckedException extends Exception {
public NestedCheckedException(String msg);
public NestedCheckedException(String msg, Throwable cause);
public String getMessage();
public Throwable getRootCause();
public Throwable getMostSpecificCause();
public boolean contains(Class<?> exType);
public static String buildMessage(String message, Throwable cause);
}Usage Examples
// Create custom exceptions with nested support
public class DataAccessException extends NestedRuntimeException {
public DataAccessException(String msg) {
super(msg);
}
public DataAccessException(String msg, Throwable cause) {
super(msg, cause);
}
}
// Use nested exceptions
try {
// Some database operation
connection.execute(sql);
} catch (SQLException ex) {
// Wrap with more specific exception
throw new DataAccessException("Failed to execute query", ex);
}
// Handle nested exceptions
try {
someMethod();
} catch (DataAccessException ex) {
Throwable rootCause = ex.getRootCause(); // Gets original SQLException
Throwable mostSpecific = ex.getMostSpecificCause();
if (ex.contains(SQLException.class)) {
// Handle SQL-specific error
}
}Spring provides mechanisms for discovering parameter names at runtime.
ParameterNameDiscoverer Interface
public interface ParameterNameDiscoverer {
String[] getParameterNames(Method method);
String[] getParameterNames(Constructor<?> ctor);
}
public class DefaultParameterNameDiscoverer extends PrioritizedParameterNameDiscoverer {
public DefaultParameterNameDiscoverer();
}
public class PrioritizedParameterNameDiscoverer implements ParameterNameDiscoverer {
public void addDiscoverer(ParameterNameDiscoverer pnd);
@Override
public String[] getParameterNames(Method method);
@Override
public String[] getParameterNames(Constructor<?> ctor);
}
public class StandardReflectionParameterNameDiscoverer implements ParameterNameDiscoverer {
@Override
public String[] getParameterNames(Method method);
@Override
public String[] getParameterNames(Constructor<?> ctor);
}Usage Examples
// Discover parameter names
ParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();
public void processUser(String firstName, String lastName, int age) { }
Method method = MyClass.class.getMethod("processUser", String.class, String.class, int.class);
String[] paramNames = discoverer.getParameterNames(method);
// Returns: ["firstName", "lastName", "age"] (if compiled with -parameters flag)
// Use with constructors
public class User {
public User(String name, String email, int age) { }
}
Constructor<?> constructor = User.class.getConstructor(String.class, String.class, int.class);
String[] constructorParams = discoverer.getParameterNames(constructor);GenericTypeResolver Utility
public abstract class GenericTypeResolver {
public static Class<?> resolveParameterType(MethodParameter methodParameter, Class<?> implementationClass);
public static Class<?> resolveReturnType(Method method, Class<?> clazz);
public static Class<?> resolveReturnTypeArgument(Method method, Class<?> genericIfc);
public static Class<?> resolveTypeArgument(Class<?> clazz, Class<?> genericIfc);
public static Class<?>[] resolveTypeArguments(Class<?> clazz, Class<?> genericIfc);
public static Type resolveType(Type genericType, Class<?> contextClass);
public static Class<?> resolveType(Type genericType, Map<TypeVariable<?>, Type> map);
}Usage Examples
// Resolve generic types in inheritance hierarchies
public interface Repository<T> {
void save(T entity);
List<T> findAll();
}
public class UserRepository implements Repository<User> {
// Implementation
}
// Resolve the generic type T = User
Class<?> entityType = GenericTypeResolver.resolveTypeArgument(
UserRepository.class, Repository.class); // Returns User.class
// Resolve method return types
Method findAllMethod = Repository.class.getMethod("findAll");
Class<?> returnType = GenericTypeResolver.resolveReturnType(
findAllMethod, UserRepository.class); // Returns List.class
Class<?> elementType = GenericTypeResolver.resolveReturnTypeArgument(
findAllMethod, UserRepository.class); // Returns User.classSpringVersion Utility
public final class SpringVersion {
public static String getVersion();
// Private constructor - utility class
}Usage Example
// Get Spring version at runtime
String version = SpringVersion.getVersion(); // e.g., "6.2.8"
System.out.println("Running Spring Framework version: " + version);Core Callback Interfaces
@FunctionalInterface
public interface MethodCallback {
void doWith(Method method) throws IllegalArgumentException, IllegalAccessException;
}
@FunctionalInterface
public interface FieldCallback {
void doWith(Field field) throws IllegalArgumentException, IllegalAccessException;
}
@FunctionalInterface
public interface MethodFilter {
boolean matches(Method method);
MethodFilter USER_DECLARED_METHODS = (method -> !method.isBridge() && !method.isSynthetic());
}
@FunctionalInterface
public interface FieldFilter {
boolean matches(Field field);
}Exception Depth Comparator
public class ExceptionDepthComparator implements Comparator<Class<? extends Throwable>> {
public ExceptionDepthComparator(Throwable exception);
public ExceptionDepthComparator(Class<? extends Throwable> targetException);
@Override
public int compare(Class<? extends Throwable> o1, Class<? extends Throwable> o2);
public static Class<? extends Throwable> findClosestMatch(
Collection<Class<? extends Throwable>> exceptionTypes,
Throwable targetException);
}This core infrastructure provides the foundational building blocks that enable Spring's dependency injection container, aspect-oriented programming capabilities, and other advanced features throughout the framework.
Install with Tessl CLI
npx tessl i tessl/maven-org-springframework--spring-core