注解&动态代理
注解&动态代理
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() {
    }
}
                    
                
                
            
        
浙公网安备 33010602011771号