反射和AOP练习笔记
练习通过反射获取注解上的参数
TestTag
定义一个注解并设置注解参数类型为一个String[]。
package tag;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestTag {
String[] value();
}
FirstTest
在这个类中使用@TestTag注解,并设置几个参数。
package funImpl;
import tag.TestTag;
public class FirstTest{
@TestTag(value = {"这是", "注解", "中", "传的参数"})
public void tag() {
System.out.println("tag方法");
}
}
main
通过反射获取FirstTest的Class对象,并将 @TestTag中的参数打印出来:
import funImpl.FirstTest;
import tag.TestTag;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
public class main {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
//反射
Class testClass= Class.forName(FirstTest.class.getName());
FirstTest firstTest = (FirstTest) testClass.newInstance();
//获取方法
Method[] methods = testClass.getDeclaredMethods();
//遍历方法
Arrays.stream(methods)
.filter(m -> m.getName().equals("tag"))//获取tag方法对象
.forEach(m -> {//打印注解里的值
try {
m.invoke(firstTest);//调用tag方法
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
TestTag annotation = m.getAnnotation(TestTag.class);
Arrays.stream(annotation.value()).forEach(System.err::println);
});
}
}
结果如下。
练习AspectJX
- AspectJX传送门
-
AspectJ使用教程
接下来将以一个装B的方式去设置界面的标题。首先先定义一个注解,参数接收类型设为String。
package com.lyan.test;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {
String value();
}
然后创建一个切面类,当执行完onCreate()方法后,修改一下界面的标题。
package com.lyan.test;
import android.support.v7.app.AppCompatActivity;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
//(@Around ProceedingJoinPoint joinPoint.proceed())
//(@Before @After JoinPoint)
@Aspect
public class TestAspect {
/**
* 匹配任意路径下的xxActivity的onCreate方法
*/
@Pointcut("execution(@com.lyan.test.Test void *..*Activity.onCreate(android.os.Bundle))")
public void cutPoint() {
}
/**
* 匹配AppCompatActivity这个类型
*/
@Pointcut("target(android.support.v7.app.AppCompatActivity)")
public void cutTarget() {
}
@After("cutPoint() && cutTarget()")
public void afterActivityOnCreate(JoinPoint joinPoint){
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Test annotation = signature.getMethod().getAnnotation(Test.class);
((AppCompatActivity) joinPoint.getTarget()).setTitle(annotation.value());
}
}
最后在MainActivity的onCreate()方法上添加@Test注解。
package com.lyan.test;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Test("改标题")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
运行效果如图