- 注解有特殊功能都是runtime级别的
- 注解三步:定义,使用,解析
-----定义--Target使用位置,适用范围
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno {
//注解的属性
String name();
int age() default 28;
//String value();
//String[] value();
}
------------使用
@MyAnno(name = "zhangsan")
public class MyAnnoTest {
@SuppressWarnings("all")
@MyAnno(name = "zhangsan")
//@MyAnno({ "aaa","bbb","ccc"})
public void show(String str){
System.out.println("show running...");
}
}
----------------解析
public class MyAnnoParser {
public static void main(String[] args) throws NoSuchMethodException, SecurityException {
//解析show方法上面的@MyAnno
//直接的目的是 获得show方法上的@MyAnno中的参数
//获得show方法的字节码对象
Class clazz = MyAnnoTest.class;
Method method = clazz.getMethod("show", String.class);
//获得show方法上的@MyAnno
MyAnno annotation = method.getAnnotation(MyAnno.class);
//获得@MyAnno上的属性值
System.out.println(annotation.name());//zhangsan
System.out.println(annotation.age());//28
//根据业务需求写逻辑代码
}
}
----------其他注解方式
//压制警告
public class AnnoDemo {
public static void main(String[] args) {
@SuppressWarnings({ "unused", "rawtypes" })
List list = new ArrayList();
show();
}
//定义方法过时
@Deprecated
public static void show(){
}
public static void show(String xx){
}
//帮助开发人间检查是否覆盖父类的方法发正确
@Override
public String toString() {
// TODO Auto-generated method stub
return super.toString(); }
}
- 动态代理也可增强,但一般用于拦截
- 动态代理必须与目标对象有相同的接口
----requset一般转为http
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
final HttpServletRequest req = (HttpServletRequest) request;
//使用动态代理完成全局编码
HttpServletRequest enhanceRequset = (HttpServletRequest) Proxy.newProxyInstance(
req.getClass().getClassLoader(),
req.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//对getParameter方法进行增强
String name = method.getName();//获得目标对象的方法名称
if("getParameter".equals(name)){
String invoke = (String) method.invoke(req, args);//乱码
//转码
invoke = new String(invoke.getBytes("iso8859-1"),"UTF-8");
return invoke;
}
return method.invoke(req, args);
}
}
);
chain.doFilter(enhanceRequset, response);
}
1.类加载器
- 类加载器就加载字节码文件(.class)
![](https://img.haomeiwen.com/i5109746/3f4e14bb5a0b2ce9.png)
- 1)BootStrap:引导类加载器:加载都是最基础的文件
2)ExtClassLoader:扩展类加载器:加载都是基础的文件
3)AppClassLoader:应用类加载器:三方jar包和自己编写java文件
ClassLoader 字节码对象.getClassLoader();
2.注解
- 给jvm看的,给机器看的注解优点:开发效率高 成本低
注解缺点:耦合性大 并且不利于后期维护
- @Override:告知编译器此方法是覆盖父类的
@Deprecated:标注过时
@SuppressWarnings:压制警告
- @Retention
SOURCE: 注解在源码级别可见
CLASS:注解在字节码文件级别可见
RUNTIME:注解在整个运行阶段都可见
@Target
代表注解修饰的范围:类上使用,方法上使用,字段上使用
FIELD:字段上可用此注解
METHOD:方法上可以用此注解
TYPE:类/接口上可以使用此注解
3.动态代理
- static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
- 返回值:Object就是代理对象
参数:
loader:代表与目标对象相同的类加载器-------目标对象.getClass().getClassLoader()
interfaces:代表与目标对象实现的所有的接口字节码对象数组
h:具体的代理的操作,InvocationHandler接口
注意:JDK的Proxy方式实现的动态代理 目标对象必须有接口 没有接口不能实现jdk版动态代理
-----------接口
public interface TargetInterface {
public void method1();
public String method2();
public int method3(int x);
}
----------实现类
public class Target implements TargetInterface{
@Override
public void method1() {
System.out.println("method1 running...");
}
@Override
public String method2() {
System.out.println("method2 running...");
return "method2";
}
@Override
public int method3(int x) {
return x; } }
--------------动态代理必须实现相同接口
public class ProxyTest2 {
public static void main(String[] args) {
final Target target = new Target();
// 动态创建代理对象
TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(), // 或者new Class[]{TargetInterface.class},
new InvocationHandler() {
@Override
// 被执行几次?------- 看代理对象调用方法几次
// 代理对象调用接口相应方法 都是调用invoke
/*
* proxy:是代理对象 method:代表的是目标方法的字节码对象 args:代表是调用目标方法时参数
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 反射知识点
Object invoke = method.invoke(target, args);// 目标对象的相应方法
// retrun返回的值给代理对象
return invoke;
}
});
proxy.method1();// 调用invoke---Method:目标对象的method1方法 args:null 返回值null
String method2 = proxy.method2();// 调用invoke---Method:目标对象的method2方法
// args:null 返回值method2
int method3 = proxy.method3(100);//// 调用invoke-----Method:目标对象的method3方法
//// args:Object[]{100} 返回值100
System.out.println(method2);
System.out.println(method3);
}
}
网友评论