上一篇在这儿:
http://blog.csdn.net/wkgcass/article/details/43954249
大致说了一些基础功能。这篇来看看它全部的功能
1.全自动
如果注入没有歧义,没有特别的需求,只是要完成注入,则只要extends AutoWire,或者对类定义处进行@Wire注解标明,即可完成注入
不过对于@Wire注解标注的类,直接使用new来实例化是不能自动注入的,但是继承AutoWire的类可以随意实例化,若在实例化过程中“遇到”@Wire注解的类,就会对@Wire标注的类进行自动注入。
如果有歧义或者额外的需求(比如不希望某个setter被执行,或者强制让值为某个bean),比如setter是以接口方式定义的,就需要注解的帮忙了。
2.注解:
在框架使用中,通过注解进行配置是非常方便的,可以减少很多的xml语句。
所以,为了尽可能简单,必须指定配置的地方都使用注解完成。
默认提供这些注解:
@Target(ElementType.TYPE)
public @interface Bean {
public String[] name(); //bean的名称,以String数组形式存放多个名称
public boolean isSingleton() default true; //是否为单例
}
@Target({ElementType.TYPE, ElementType.CONSTRUCTOR})
public @interface Default {
public Class<?> clazz() default Default.class; //遇到时默认使用哪个类(在constructor上标注时这个字段不会考虑)
public String bean() default ""; //遇到时默认使用哪个bean(在constructor上标注时这个字段不会考虑)
}
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
public @interface Force {
public String[] value(); //强制使用某个值
public String[] in() default ""; //指定在哪个bean中使用
}
@Target( {ElementType.FIELD, ElementType.METHOD})
public @interface Ignore { //忽略某个setter
}
@Target(ElementType.TYPE)
public @interface IsSingleton { //指定该类为单例(只允许被实例化一次)
}
@Target( { ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
public @interface Use {
public Class<?>[] clazz() default Use.class; //指定使用哪个类
public String[] bean() default ""; //指定使用哪个bean
public String[] in() default ""; //指定在哪个bean中使用上述参数
}
@Target(ElementType.TYPE)
public @interface Wire { //在装配过程中如果遇到则进行自动装配
}
从上述代码,以及注释中可以了解每个Annotation的功能以及用在何处(@Target注解标明了位置)。
所以用法也显而易见了~~稍稍举一反三一下就好。
3.自定注解 / 注解解释
一个没有扩展性的程序不是好程序
——wkgcass
开个玩笑= =
扩展性对程序是极其重要的。这里最大的可扩展点就是注解。所以注解必须可扩展
那么如何扩展呢?看如下4个接口:
public interface ConstructorFilter {
boolean canHandle(Set<Annotation> annotations);
Constructor<?> handle(Constructor<?>[] cons, ConstructorFilterChain chain) throws AnnotationHandlingException;
double priority();
}
public interface ParamAnnotationHandler {
boolean canHandle(Annotation[] annotations);
Object handle(Member caller, Class<?> cls,Annotation[] toHandle, ParamHandlerChain chain) throws AnnotationHandlingException;
double priority();
}
public interface SetterAnnotationHandler {
boolean canHandle(Set<Annotation> annotations);
boolean handle(Object target, Method setter, Set<Annotation> toHandle, SetterHandlerChain chain) throws AnnotationHandlingException;
double priority();
}
public interface TypeAnnotationHandler {
boolean canHandle(Annotation[] annotations);
Object handle(Class<?> cls, TypeHandlerChain chain) throws AnnotationHandlingException;
double priority();
}
从上到下依次为:
Constructor过滤器,用于选取特定的构造器,返回选取后的过滤器,选取失败返回null
参数注解处理,返回生成/取出的参数,失败则抛出异常
Setter注解处理,用于执行(invoke)指定的setter,执行成功返回true,失败返回false
类型注解处理,用于对类型进行操作,比如@Default注解,就需要这类接口实现一个handler去选取指定的类。
大家还能发现,每个接口的handle方法都有一个chain参数,它是这儿编程思想的主体之一
其中priority作用是区分先后。数值越低,则在chain中排得越早。注意:如果priority相同,那么相同数值的所有同类型handler只有一个会执行。
一个例子代码:
/**
* Priority 0.0
* <br/>
* Default implementation of ParamAnnotationHandler
* <br/> simply return the corresponding value of given parameter type.
* @author wkgcass
*
*/
public class DefaultParamHandler extends IOCController implements
ParamAnnotationHandler {
//本工具默认的参数handler
@Override
public boolean canHandle(Annotation[] annotations) {
return true; //不管什么类型都能处理
}
@Override
public Object handle(Member caller, Class<?> cls, Annotation[] toHandle,
ParamHandlerChain chain) throws AnnotationHandlingException {
if(AutoWire.DEBUG_MODE){ //一个syso,debug时候用来看执行过程,这儿不用管它
System.out.println(this.getClass().getSimpleName()+" "+cls);
}
try{
return chain.next().handle(caller, cls, toHandle, chain); //先执行chain的下一个handler,
//如果失败再接着走,成功则返回
}catch(AnnotationHandlingException e){}
if(AutoWire.DEBUG_MODE){ //一个syso,不用管它
System.out.println(this.getClass().getSimpleName()+" start");
}
return get(cls); //返回获取的值,这儿get是IOCController中的一个用来方便handlers操作的方法,具体功能见下一篇。
}
@Override
public double priority() {
return 0.0;
}
}
并且在IOCController中注册(调用static的register方法)即可
以类似的方式,可以完成更多自定义注解操作!