自定义注解
定义:注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
开发步骤
创建一个@interface
String value();抽象方法用以接收数据
使用元注解,描述自定义注解
@Target指定注解可以加在哪里
ElementType.TYPE:可在类和接口上面
ElementType.METHOD:可方法上
ElementType.FIELD:可在属性@Retention指定注解在什么时候有用
RetentionPolicy.RUNTIME:注解保留到运行时
RetentionPolicy.ClASS:注解保留到Class文件中
RetentionPolicy.SOURCE:注解保留到java编译时期@Inherited可以被继承
jdk动态代理
- 被代理类必须实现一个接口,任意接口
public class Bus implements Runnable{}
- 创建一个类实现InvocationHandler,该类用来对象代理对象进行方法的增强
public class TimeInvocation implements InvocationHandler{
private Object target;//被代理对象
public TimeInvocation(Object target){
this.target=target;
}
}
- 在invoke()方法中调用被代理对象的方法,并且添加增强的代码
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long time1=System.currentTimeMillis();
//调用被代理对象的方法
method.invoke(target, args);
long time2=System.currentTimeMillis();
System.out.println(time2-time1);
return null;
}
通过Proxy.newProxyInstance(ClasLoader, Class, InvovationHandler)创建代理类对象
调用代理对象的方法
TimeInvocation time=new TimeInvocation(s);
Class<?> clazz=s.getClass();
Runnable s1= (Runnable)Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), time);
s1.run();
cglib
public class SayHello {
public void say(){
System.out.println("hello everyone");
}
}
public class CglibProxy implements MethodInterceptor{
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz){
//设置需要创建子类的类
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
//通过字节码技术动态创建子类实例
return enhancer.create();
}
//实现MethodInterceptor接口方法
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("前置代理");
//通过代理类调用父类中的方法
Object result = proxy.invokeSuper(obj, args);
System.out.println("后置代理");
return result;
}
}
public class DoCGLib {
public static void main(String[] args) {
CglibProxy proxy = new CglibProxy();
//通过生成子类的方式创建代理类
SayHello proxyImp = (SayHello)proxy.getProxy(SayHello.class);
proxyImp.say();
}
}
注意: jdk动态代理与cglib的区别
jdk通实现接口的方式实现动态代理 cglib通过继承的方式实现动态代理
jdk动态代理与cglib如何选择? CGLib创建的动态代理对象性能比JDK创建的动态代理对象的性能高不少,但是CGLib在创建代理对象时所花费的时间却比JDK多得多,所以对于单例的对象,因为无需频繁创建对象,用CGLib合适,反之,使用JDK方式要更为合适一些。同时,由于CGLib由于是采用动态创建子类的方法,对于final方法,无法进行代理。