1.前言
这篇文章主要是对上篇文章不足之处做了改进。
从上篇文章中,我们可以看出,主要给了两个注解@Component(对类注解)和Autowried注解(对成员和成员的Setter方法注解)。Autowried只能获取池子中的对象,而池子中对象都是需要给对应的类以@Component注解;对于不可更改的Jar包中的类,就没有办法增加@Component注解,也就不能实现“注入”操作。所以我们给出了一个Bean注解,Bean注解就是为了解决这样的问题存在的!
2.关于Bean注解
(1)给一个方法增加Bean注解,而将这个方法的返回值对象和返回值对象类型作为键值对,存储到池子中!我们先给出Bean注解:
@Retention(RUNTIME)
@Target(METHOD)
public @interface Bean {
}
(2)若相关类没有提供可用的构造方法;所谓的没有提供可用的构造方法包括相关构造方法是private的,或者,构造方法不能直接调用,或者,构造方法不能直接生成对象!在这种情况下,由于对于Component注解的处理是通过调用相关类的无参构造产生的,那么,对于上述情况,就不能产生这个的对象!此时,可以通过Bean注解,调用合适的获取该类对象的方法,取得这个类的对象,并加入BeanPool中!
(3)相关类的对象,不是简单无参构造就能直接使用的;意思是:这个类虽然存在无参构造,但是,无参构造出来的对象不能直接使用。那么,在这种情况下,通过Bean注解的方法,完成其对象所必须的基础数据,从而使得该对象可用!
上面介绍了Bean注解的三个应用场合,接下来我们对带有@Bean注解的方法进行处理,我们来看一下具体的代码(这里只给出了处理bean注解的代码部分,其余请参考上一篇博文):
//该方法是处理带有@Bean注解的无参方法
private static void dealBean(Class<?> klass, Object object) {
Method[] methods = klass.getDeclaredMethods();
for (Method method : methods) {
if (!method.isAnnotationPresent(Bean.class)) {
continue;
}
if (method.getParameterCount() > 0) {
continue;
}
Class<?> returnType = method.getReturnType();
try {
Object beanObject = method.invoke(object);
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setKlass(returnType);
beanDefinition.setObject(beanObject);
beanDefinition.setSingleton(true);
beanDefinition.setInject(false);
beanPool.put(returnType.getName(), beanDefinition);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
通过包扫描,扫描出带有@Component的类,将类及其对象和一些参数信息存入beanPool中,然后我们就需要调用这个方法,来遍历被扫描到的带有@Component注解的类是否有带有@Bean注解的方法,若带有,将这些方法的返回值对象和返回值对象类型作为键值对存储到池子中!若没有,不予处理!需要说明的是:这里的dealBean()方法处理的是带有@Bean注解的无惨方法。
这里我就不贴测试代码了,大家可以自行验证!
到此为止,我们只完成了依赖注入的一部分,关于对有@Bean注解且含有参数的方法的处理以及循环依赖的问题,之后我会发出来,敬请期待!