Building a Simple Spring IOC Container: XML and Annotation‑Based Bean Assembly
This article demonstrates how to create a lightweight Spring‑style IoC container in Java by parsing a properties file for XML‑like configuration, implementing annotation‑driven bean registration with a custom @Bean annotation, and adding automatic field injection using a custom @Autowired annotation, complete with full source code examples.
Introduction
After studying Spring, the author built a very simple Spring‑style IoC container that supports XML‑style bean definition, annotation‑based bean registration, and @Autowired automatic wiring. The following sections describe the design ideas and provide complete Java source code.
1. XML‑based Bean Assembly
Idea
The container reads a conf.properties file that maps interface names to implementation classes, loads the classes via Class.forName, creates instances, and stores them in a Map<Class,Object> for later retrieval.
Implementation
com.wql.dao.userDao=com.wql.daoImpl.userDaoImpl
com.wql.service.userService=com.wql.serviceImpl.userServiceImpl package com.wql.application;
import java.io.File;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class MyApplicationContext<T> {
// simulate IOC container
private Map<Class,Object> map = new HashMap<>();
private String ResourcePath;
private String filepath;
public MyApplicationContext() {
}
public MyApplicationContext(String resourcePath) {
ResourcePath = resourcePath;
}
// obtain an object of unknown type (through the map)
public T getBean(Class clazz) {
return (T)map.get(clazz);
}
// load Class objects from properties and inject into the map
public void initXMLSpringIOC() {
try{
InputStream stream = MyApplicationContext.class.getClassLoader().getResourceAsStream(ResourcePath);
Properties properties = new Properties();
properties.load(stream);
// get content
Set<Object> keys = properties.keySet();
for(Object key:keys){
// Class:instance
map.put(Class.forName(key.toString()),Class.forName(properties.getProperty(key.toString())).newInstance() );
}
}catch (Exception e){
e.printStackTrace();
}
}
// annotation‑based bean assembly
public void initAnnotationSpringIOC(){
filepath = MyApplicationContext.class.getClassLoader().getResource("").getFile();
System.out.println(filepath);
loadOne(new File(filepath));
AnnotationAutowired();
}
private void loadOne(File fileparent) {
if(fileparent.isDirectory()){
File[] files = fileparent.listFiles();
if(files.length==0||files==null){
return;
}else{
for(File file:files){
if(file.isDirectory()){
loadOne(file);
}else{
try{
String oldpath = file.getAbsolutePath().substring(filepath.length()-1,file.getAbsolutePath().length());
if(oldpath.contains(".class")){
String newpath = oldpath.replaceAll("\\\\",".").replace(".class","");
Class<?> aClass = Class.forName(newpath);
// simulate bean assembly
if(!aClass.isInterface()){
if(aClass.getAnnotation(Bean.class)!=null){
map.put(aClass.getInterfaces()[0],aClass.newInstance());
}
}
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
}
}
// automatic wiring
private void AnnotationAutowired(){
for(Map.Entry<Class,Object> entry:map.entrySet()){
Object obj = entry.getValue();
Class<?> aClass = obj.getClass();
Field[] fields = aClass.getDeclaredFields();
for(Field field: fields){
field.setAccessible(true);
if(field.getAnnotation(MyAutowired.class)!=null){
try{
field.set(obj,map.get(field.getType()));
}catch (Exception e){
e.printStackTrace();
}
}
}
}
}
}2. Annotation‑Based Bean Assembly
Idea
The container scans the compiled .class files under the project directory, converts file paths to fully‑qualified class names, checks each class for the custom @Bean annotation, and registers non‑interface classes into the map.
Implementation
package com.wql.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Bean {
} // The scanning logic is part of the loadOne method shown in the previous code block.3. @Autowired Automatic Wiring
The container iterates over all beans already stored in the map, inspects their fields, and if a field is annotated with the custom @MyAutowired annotation, the corresponding bean is injected via reflection.
package com.wql.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAutowired {
} package com.wql.serviceImpl;
import com.wql.Annotation.MyAutowired;
import com.wql.Annotation.Bean;
import com.wql.dao.userDao;
import com.wql.service.userService;
@Bean
public class userServiceImpl implements userService {
@MyAutowired
public userDao userDao;
@Override
public void test() {
userDao.test();
}
} // The AnnotationAutowired method in MyApplicationContext (shown earlier) performs the field injection.Conclusion
The article provides a complete, runnable implementation of a minimal Spring‑like IoC container, covering XML‑style configuration, annotation‑driven bean registration, and automatic dependency injection, and demonstrates its usage with simple DAO and service examples.
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.
Sohu Tech Products
A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.
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.
