死磕Java ------- 手寫IOC
阿新 • • 發佈:2018-12-09
ioc 過多的概念我再這裡就不解釋了 需要了解概念 點下邊連結
概念理解了 手寫個ioc 就明白怎麼回事了 其實ioc沒有想象中的那麼難 註解+反射 就可以搞定
這裡我是仿照spring設計的 的倆個註解 Autowired 和Component
專案結構圖
註解引入的類
import java.lang.annotation.Documented; 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)
@Documented
public @interface Autowired {
}
/**
* 指定需要容器管理的類
*
*/
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
}
先上倆個工具類吧 一個是掃描所有類的 一個是根據掃描的類注實力化物件的
import java.io.File; import java.io.FileFilter; public class ClassUtil { /** * 獲取該路徑下所遇的class檔案和目錄 * * @param pkg * @return */ public static File[] getClassFile(String filePath) { return new File(filePath).listFiles(new FileFilter() { @Override public boolean accept(File file) { return file.isFile() && file.getName().endsWith(".class") || file.isDirectory(); } }); } }
import java.io.File;
import com.annotation.Component;
import com.ioc.IocContext;
public class AnnotationUtil {
//獲取指定包路徑下實現 Component主鍵Bean的例項
public static void addClassByAnnotation(String filePath, String packageName) {
try {
File[] files = ClassUtil.getClassFile(filePath);
if (files != null) {
for (File f : files) {
String fileName = f.getName();
if (f.isFile()) {
Class<?> clazz = Class.forName(packageName + "." + fileName.substring(0, fileName.lastIndexOf(".")));
//判斷該類是否實現了註解
if(clazz.isAnnotationPresent(Component.class)) {
IocContext.applicationContext.put(clazz, clazz.newInstance());
}
} else {
addClassByAnnotation(f.getPath(), packageName + "." + fileName);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
重點來了 ,ioc 最重要的部分 iocContent 先掃描所有包 掃描到有註解的 放個 把物件 map集合裡
import java.net.URL;
import java.util.Enumeration;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.util.AnnotationUtil;
/**
* Ioc 容器實現類
*
*/
public class IocContext {
public static final Map<Class<?>, Object> applicationContext = new ConcurrentHashMap<Class<?>, Object>();
static{
// 指定需要掃描的包名
String packageName = "com";
try {
initBean(packageName);
} catch (Exception e) {
e.printStackTrace();
}
}
private static void initBean(String packageName) throws Exception {
Enumeration<URL> urls = Thread.currentThread().getContextClassLoader().getResources(packageName.replaceAll("\\.", "/"));
while (urls.hasMoreElements()) {
AnnotationUtil.addClassByAnnotation(urls.nextElement().getPath(), packageName);
}
//IOC實現, 自定注入
IocUtil.inject();
}
}
底下是業務層
import java.lang.reflect.Field;
import java.util.Map;
import java.util.Map.Entry;
import com.annotation.Autowired;
/**
* Ioc 注入實現
*
*/
public class IocUtil {
public static void inject() {
Map<Class<?>, Object> map = IocContext.applicationContext;
try {
for (Entry<Class<?>, Object> entry : map.entrySet()) {
Class<?> clazz = entry.getKey();
Object obj = entry.getValue();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(Autowired.class)) {
Class<?> fieldClazz = field.getType();
field.setAccessible(true);
Object fieldObj = map.get(fieldClazz);
field.set(obj, fieldObj);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Component
public class TestController {
@Autowired
public UserService userService;
public void getUser() {
User user = userService.getUser();
System.out.println(user);
}
}
public class User {
private String userName;
private Integer age;
private Integer sex;
public User(String userName, Integer age, Integer sex) {
this.userName = userName;
this.age = age;
this.sex = sex;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
@Override
public String toString() {
return "User [userName=" + userName + ", age=" + age + ", sex=" + sex + "]";
}
}
@Component
public class UserService {
public User getUser() {
User user = new User("張三", 50, 22);
return user;
}
}
測試
import com.demo.TestController;
import com.ioc.IocContext;
public class Main {
public static void main(String[] args) throws Exception {
TestController testController = (TestController)IocContext.applicationContext.get(TestController.class);
testController.getUser();
}
}
以上就是最簡單的ioc了
原始碼要的私聊,