java容器代码,java代码实现简易版IOC容器!

java代码实现简易版IOC容器,含IOC容器实现步骤分解

一、需求

实现一个简易的IOC容器,管理Bean,从IOC容器的BeanFactory中获取实例,从而取代自己new实例的做法。

二、实现步骤分析

5977e445945c36554857ef55095bc55d.png

三、具体代码实现

自定义注解类 MyComponent 和 MyAutowired:

1 package MyIOCAndMyAop.Annotations;

2

3 import java.lang.annotation.ElementType;

4 import java.lang.annotation.Retention;

5 import java.lang.annotation.RetentionPolicy;

6 import java.lang.annotation.Target;

7

8 @Target(ElementType.TYPE)

9 @Retention(RetentionPolicy.RUNTIME)

10 public @interface MyComponent {

11

12 }

1 package MyIOCAndMyAop.Annotations;

2

3 import java.lang.annotation.ElementType;

4 import java.lang.annotation.Retention;

5 import java.lang.annotation.RetentionPolicy;

6 import java.lang.annotation.Target;

7

8 @Target(ElementType.FIELD)

9 @Retention(RetentionPolicy.RUNTIME)

10 public @interface MyAutowired {

11

12 }

MyIOC容器的实现:自己实现简单的IOC容器,来管理bean:BeanFactory,String为全类名,Object为通过类加载器加载进来的Class对象反射创建的bean。

1 package MyIOCAndMyAop;

2

3 import java.io.File;

4 import java.lang.annotation.Annotation;

5 import java.lang.reflect.Field;

6 import java.lang.reflect.InvocationTargetException;

7 import java.lang.reflect.Method;

8 import java.net.MalformedURLException;

9 import java.net.URL;

10 import java.net.URLClassLoader;

11 import java.util.ArrayList;

12 import java.util.HashMap;

13 import java.util.Map;

14 import MyIOCAndMyAop.Annotations.MyAutowired;

15 import MyIOCAndMyAop.Annotations.MyComponent;

16

17 public class MyIOC {

18

19 // beanFactory 要声明为类变量,因为它不能被GC回收:

20 private static HashMap beanFactory = new HashMap<>();

21

22 /**

23 * 随着MyIOC类被加载到内存进行初始化,就会执行其静态代码块

24 * @param args

25 */

26 static {

27 init();

28 }

30

31 /**

32 * 获取BeanFactory

33 * @return

34 */

35 public static HashMap getBeanFactory(){

36 return beanFactory;

37 }

38

39 /**

40 * 根据全类名更新BeanFactory中的bean

41 * @param typeName

42 * @param proxyInstance

43 */

44 public static void updateBeanFromBeanFactory(String typeName, Object proxyInstance) {

45 beanFactory.put(typeName, proxyInstance);

46 }

47

48 /**

49 * 通过全类名获得对应的实例

50 * @param completeClassName

51 * @return

52 */

53 public static Object getBean(String completeClassName) {

54 return beanFactory.get(completeClassName);

55 }

56

57 public static void init() {

58 HashMap loadedClazzList;//

59 try {

60 //1.加载指定的类

61 File file = new File("C:\\workplace\\test\\bin");//!!!这里写死了路径不合适,可以做改进

62 loadedClazzList = loadAllClazz(file);

63

64 //2.实例化并放入IOC容器中:对于那些有注解的类,做实例化

65 newInstance(loadedClazzList);

66

67 // 3.完成依赖注入

68 autoWired();

69

70 // 4.测试:找到beanFactory中的某个bean,并执行其某个方法 ===> 这里有个问题,只能执行指定的方法,所以beanFactory中的所有bean都得有这个方法,这里先这么做了,但这明显不合理。

71 // test();

72 } catch (Exception e) {

73 e.printStackTrace();

74 }

75 }

76

77 public static void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

78 for(Map.Entry entry : beanFactory.entrySet()) {

79 // System.out.println(entry.getKey() + " ---> ");

80 Method method = entry.getValue().getClass().getMethod("test");

81 method.invoke(entry.getValue());

82 }

83 }

84

85 /**

86 * 对BeanFactory中管理的所有bean完成依赖注入。

87 * 交给IOC容器管理的类,需要注入成员变量,如果该成员变量是自定义的类,该类也是需要交给IOC容器管理的。

88 * @throws IllegalAccessException

89 * @throws IllegalArgumentException

90 * @throws MalformedURLException

91 * @throws ClassNotFoundException

92 */

93 public static void autoWired() throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, MalformedURLException {

94 for(Map.Entry entry : beanFactory.entrySet()) {

95 Field[] fields = entry.getValue().getClass().getDeclaredFields();//!!!getFields():只能获取到运行时类中及其父类中声明为public的属性;getDeclaredFields():获取运行时类本身声明的所有的属性

96 for(Field field : fields) {

97 Annotation[] annotations = field.getAnnotations();

98 for(int i = 0; i < annotations.length; i++) {

99 if(annotations[i].annotationType() == MyAutowired.class) {

100 //从beanFactory中找到相应的bean,赋值给该成员变量,以完成依赖注入。

101 Object object = beanFactory.get(field.getType().getTypeName());

102 // System.out.println(field.getType().getTypeName());//MyIOCAndMyAop.bean.Student

103 //通过Field(反射)为成员变量赋值:

104 field.setAccessible(true);

105 field.set(entry.getValue(), object);

106 }

107 }

108 }

109 }

110 }

111

112 /**

113 * 实例化: 放到loadedClazzlist集合中的Class对象都是需要做实例化的(加了@MyComponent注解的类)

114 */

115 public static void newInstance(HashMap loadedClazzList) throws InstantiationException, IllegalAccessException, ClassNotFoundException, MalformedURLException {

116 for(Map.Entry entry : loadedClazzList.entrySet()) {

117 beanFactory.put(entry.getKey(), entry.getValue().newInstance());

118 }

119 }

120

121 /**

122 * 加载指定路径下的类。

123 * 类加载:javase/src/classLoader/a01helloworld/A03GetExtClassLoader

124 * @return 类加载器加载进来的指定路径下的所有Class对象

125 * @throws IllegalAccessException

126 * @throws InstantiationException

127 */

128 public static HashMap loadAllClazz(File file) throws ClassNotFoundException, MalformedURLException, InstantiationException, IllegalAccessException {

129 //用于存放类加载器加载进来的Class对象

130 HashMap loadedClazzList = new HashMap<>();

131

132 URL[] urls = new URL[]{file.toURI().toURL()};

133 URLClassLoader classLoader = new URLClassLoader(urls);

134

135 ArrayList allCompleteClassName = getAllCompleteClassName(file);

136

137 for(String element : allCompleteClassName) {

138 Class> clazz = classLoader.loadClass(element);

139 Annotation[] annotations = clazz.getAnnotations();// !!!拿到Class对象的时候,就进行筛选出有注解的Class再放到容器中,而不是把指定路径下的所有类都加载进来。

140 for(int i = 0; i < annotations.length; i++) {

141 if(annotations[i].annotationType() == MyComponent.class) {

142 loadedClazzList.put(element, clazz);//得到各个类对象了

143 }

144 }

145 }

146 return loadedClazzList;

147 }

148

149 /**

150 * 得到allNeedLoadClassFiles中所有要加载的class文件的全类名

151 */

152 private static ArrayList getAllCompleteClassName(File file) {

153 // 所有要加载的class的全类名,如:classLoader.a02myclassloader.bean.Bean

154 ArrayList completeClassNames = new ArrayList<>();

155 // 用于存放指定路径下所有要加载的class文件

156 ArrayList allNeedLoadClassFiles = new ArrayList();

157

158 getAllNeedLoadClassFile(file, allNeedLoadClassFiles);

159

160 for (File element : allNeedLoadClassFiles) {

161 String filePath = element.getPath().replace("\\", ".");

162

163 if(filePath.endsWith(".class")) {

164 //filePath.indexOf("bin.")+4:"bin."之后。filePath.lastIndexOf(".class"):".class"之前,该方法是从后往前找,性能更高。

165 String completeClassName = filePath.substring(filePath.indexOf("bin.")+4, filePath.lastIndexOf(".class"));

166 completeClassNames.add(completeClassName);

167 }

168 }

169 return completeClassNames;

170 }

171

172 /**

173 * 通过递归获取指定路径下所有要加载的class文件

174 * 递归:javase/src/recursion/A_PrintFolder

175 * @param file

176 */

177 private static ArrayList getAllNeedLoadClassFile(File file, ArrayList allNeedLoadClassFiles) {

178 if(!file.exists()) {//!!!这里要多一层判断

179 return allNeedLoadClassFiles;

180 }

181

182 if (file.isDirectory()) {//是文件夹

183 File[] listFiles = file.listFiles();

184 for (File element : listFiles) {

185 getAllNeedLoadClassFile(element, allNeedLoadClassFiles);

186 }

187 } else {//是文件

188 allNeedLoadClassFiles.add(file);

189 }

190 return allNeedLoadClassFiles;

191 }

192 }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值