注解&动态代理
1.注解
- 什么是注解
Annotation,注解,是一种代码级别的说明,和类、接口、枚举在同一层次。
- 注解作用
- 编译检查:让编译器实现基本的编译检查,如@Override
- 代码分析:对代码进行分析,从而达到取代xml的目的
- 编写文档:辅助生成帮助文档对应的内容
1.1JDK提供的注解
-
@Deprecated
表示被修饰的方法已经过时,过时的方法不建议使用,但仍可以使用。
@Deprecated public void method1(){ }
-
Override
JDK5表示覆写父类的方法,JDK6还可以表示实现接口的方法。
@Override public void start() { super.start(); }
-
@SuppressWarnings("")
表示抑制警告,被修饰的类或方法如果存在编译警告,将被编译器忽略。
deprecation:忽略过时;
rawtypes:忽略类型安全;
unused:忽略不使用;
unchecked:忽略安全检查;
null:忽略空指针;
all:忽略所有。
//3.抑制警告 //3.1deprecation,忽略过时警告 //null,忽略str空指针 @SuppressWarnings({"deprecation","null"}) public void method2(){ //3.2rawtypes,忽略类型安全警告,没有使用泛型 //unused,忽略未使用警告 @SuppressWarnings({"rawtypes","unused"}) List list=new ArrayList(); String str=null; str.toString(); }
1.2自定义注解
- 定义注解
public @interface MyAnno1 {
}
- 定义带属性的注解
属性格式:修饰符 返回值类型 属性名() default 默认值;
- 修饰符默认且只能是public abstract
- 返回值类型:基本类型、字符串String、Class、注解、枚举,以及以上类型的一维数组
- 属性名自定义
- default 默认值:可省略
public @interface MyAnno2 {
String username() default "jack";
int age();
String[] strs();
Class clazz() default Date.class;
MyAnno1 myAnno();
Color color();
}
enum Color{
BLUE,RED,YELLOW
}
1.2.1使用自定义注解
@MyAnno1
@MyAnno2(
username="tom",
age=18,
strs={"aaa","bbb","ccc"},
clazz=String.class,
myAnno=@MyAnno1,
color=Color.RED
)
public class AnnotationDemo2 {
}
1.2.2解析自定义注解
如果需要获得注解上设置的数据,那么就必须对注解进行解析,JDK提供java.lang.reflect.AnnotatedElement接口允许在运行时通过反射获得注解。
1.3元注解
用于修饰注解的注解,可以修饰自定义注解以及JDK提供的注解。
1.4案例:自定义实现类似Junit@Test
- MyJunitTest
@Retention(RetentionPolicy.RUNTIME)
//定义注解的时候,需要通过元注解Retention说明当前自定义注解的作用域(Class,Source,Runtime)
@Target(ElementType.METHOD)
//定义注解的时候,需要通过元注解Target说明当前的自定义注解的目标对象
public @interface MyJunitTest {
long timeout() default -1;//自定义属性,默认值为-1
}
/*
@Retention和@Target这两个注解是必须的,否则Demo1中的method.isAnnotationPresent(MyJunitTest.class)结果一直都为false
*/
- Demo1
public class Demo1 {
static{
System.out.println("Demo1类被加载了");
}
@MyJunitTest(timeout=1000)
public void method1(){
System.out.println("--method1--");
}
@MyJunitTest
public void method2(){
System.out.println("--method2--");
}
@MyJunitTest
public void method3(){
System.out.println("--method3--");
}
public void method4(){
System.out.println("--method4--");
}
}
- Test1
//找到Demo1的所有带有@MyJunitTest注解的方法
public class Test1 {
public static void main(String[] args) throws Exception {
//1.将Demo1的字节码文件加载到内存,获取字节码文件在内存中的对象
Class clazz=Class.forName("com.itheima.annotation2.Demo1");
//2.获取Demo1及其父类的所有方法
Method[] methods = clazz.getMethods();
//3.遍历找出带@MyJunitTest注解的方法
for (Method method:methods){
if (method.isAnnotationPresent(MyJunitTest.class)){
method.invoke(new Demo1());
System.out.println(method.getName());
}
}
}
}
2.动态代理
Proxy.newProxyInstance(ClassLoader loader,Class<?> interfaces, InvocationHandler h);
如:
Proxy.newProxyInstance(EncodingFilter.class.getClassLoader(), request.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return null;
}
})
2.1案例:解决get/post请求乱码问题
- EncodingFilter
@WebFilter("/*")
public class EncodingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
final HttpServletRequest request=(HttpServletRequest)servletRequest;
HttpServletRequest requestProxy=(HttpServletRequest) Proxy.newProxyInstance(EncodingFilter.class.getClassLoader(),
request.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//指定增强getParameter方法,再分别根据post和get请求进行处理
if("getParameter".equals(method.getName())){
String requestMethod = request.getMethod();
System.out.println(requestMethod);
if("get".equalsIgnoreCase(requestMethod)){
String value=(String) method.invoke(request,args);
System.out.println("value"+value);
return value;
//return new String(value.getBytes("ISO-8859-1"),"UTF-8");//测试发现无需转码就没有乱码
}else{
request.setCharacterEncoding("UTF-8");
return method.invoke(request,args);
}
}else{
return method.invoke(request,args);
}
}
});
filterChain.doFilter(requestProxy,servletResponse);
}
@Override
public void destroy() {
}
}