注解&动态代理

注解&动态代理

1.注解

  • 什么是注解

Annotation,注解,是一种代码级别的说明,和类、接口、枚举在同一层次。

  • 注解作用
  1. 编译检查:让编译器实现基本的编译检查,如@Override
  2. 代码分析:对代码进行分析,从而达到取代xml的目的
  3. 编写文档:辅助生成帮助文档对应的内容

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 默认值;

  1. 修饰符默认且只能是public abstract
  2. 返回值类型:基本类型、字符串String、Class、注解、枚举,以及以上类型的一维数组
  3. 属性名自定义
  4. 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() {
    }
}
posted @ 2020-10-26 16:48  ALiWang1123  阅读(228)  评论(0编辑  收藏  举报