注解的作用和意义
注解本身没有任何意义,单独的注解就是一种注释,它需要配合一些技术如反射、插桩才有意义。
注解Annotation称为Java标注,JDK1.5引入的一种注释机制。是元数据的一种形式,提供有关程序但不属于程序本身的数据。
注解对它们的注解的代码没有任何影响
package com.hello.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.SOURCE)
public @interface Hello {
String value() default "aa";
}
级别 | 技术 | 说明 |
---|
SOURCE | APT | 注解处理器在编译器能够获取注解与注解声明的类,包括类中所有成员,一般用于生成额外的辅助类 |
CLASS | 字节码增强 | 在编译出Class后,通过修改Class以实现修改代码逻辑的目的。如各种 ORM 框架、Spring AOP、热部署 |
RUNTIME | 反射 | 在运行期间,通过反射获取注解与元素,完成不同的逻辑判定 |
META-INF/services/javax.annotation.processing.Processor文件夹下新建
javax.annotation.processing.Processor文件内容为注解处理器的全路径com.example.android.annotationtest.HelloProcessor
package com.example.android.annotationtest;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Messager;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
@SupportedAnnotationTypes("com.example.android.annotationtest.Hello")
@SupportedSourceVersion(value = SourceVersion.RELEASE_7)
public class HelloProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
Messager messager = processingEnv.getMessager();
messager.printMessage(Diagnostic.Kind.NOTE, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
return false;
}
}
插桩
插桩是将一段代码插入到另一段代码,或者替换另一段代码。字节码插桩顾名思义就是在我们编写的源码编译成字节码后,
在Android生成dex之前修改class文件,修改或者增强原有代码逻辑的操作。
反射
反射是一开始并不知道我要初始化的类的对象是什么,自然也无法使用new关键字来创建对象。这时候,我们
使用JDK提供的反射API进行反射调用。反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有
属性和方法;对任意一个对象,都能够调用它的任意方法和属性;并且改变它的属性,是java被视为动态语言的关键。
buffernife
采用反射+注解 实现findViewById
public class InjectUtils {
public static void inject(Activity activity) {
Class<? extends Activity> aClass = activity.getClass();
Field[] declaredFields = aClass.getDeclaredFields();
for (Field item : declaredFields) {
if (item.isAnnotationPresent(InjectView.class)) {
InjectView annotation = item.getAnnotation(InjectView.class);
int value = annotation.value();
View viewById = activity.findViewById(value);
item.setAccessible(true);
try {
item.set(activity, viewById);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectView {
@IdRes int value();
}
public class TestInjectActivity extends AppCompatActivity {
@InjectView(R.id.content)
private TextView content;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
InjectUtils.inject(this);
content.setText("hello");
}
}
public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("com.hello.testproxy.ActivityTaskManager");
//IActivityTaskManager对应的子类
Method method = cls.getMethod("getService");
method.invoke(null);
Field iActivityTaskManagerSingletonField = cls.getDeclaredField("iActivityTaskManagerSingleton");
iActivityTaskManagerSingletonField.setAccessible(true);
Object singleton = iActivityTaskManagerSingletonField.get(null);
System.out.println("singleton:" + singleton);
Class<?> aClass = Class.forName("com.hello.testproxy.Singleton");
Field mInstance = aClass.getDeclaredField("mInstance");
mInstance.setAccessible(true);
Object o = mInstance.get(singleton);
System.out.println("obj:" + o);
Object proxy = Proxy.newProxyInstance(o.getClass().getClassLoader(), o.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("method>>>" + method.getName());
return method.invoke(o, args);
}
});
mInstance.set(singleton, proxy);
ActivityTaskManager.getService().task();
}
public class ActivityTaskManager {
public static IActivityTaskManager getService() {
return iActivityTaskManagerSingleton.get();
}
private static final Singleton<IActivityTaskManager> iActivityTaskManagerSingleton = new Singleton<IActivityTaskManager>() {
@Override
public IActivityTaskManager create() {
return new TaskManager();
}
};
}
public abstract class Singleton<T> {
private T mInstance;
public abstract T create();
public final T get() {
synchronized (this) {
if (mInstance == null) {
mInstance = create();
}
return mInstance;
}
}
}