自定義注解
定義:注解(Annotation),也叫元數(shù)據(jù)。一種代碼級(jí)別的說明。它是JDK1.5及以后版本引入的一個(gè)特性,與類、接口、枚舉是在同一個(gè)層次。它可以聲明在包、類、字段、方法、局部變量、方法參數(shù)等的前面,用來對(duì)這些元素進(jìn)行說明,注釋。
開發(fā)步驟
創(chuàng)建一個(gè)@interface
String value();抽象方法用以接收數(shù)據(jù)
使用元注解,描述自定義注解
@Target指定注解可以加在哪里
ElementType.TYPE:可在類和接口上面
ElementType.METHOD:可方法上
ElementType.FIELD:可在屬性@Retention指定注解在什么時(shí)候有用
RetentionPolicy.RUNTIME:注解保留到運(yùn)行時(shí)
RetentionPolicy.ClASS:注解保留到Class文件中
RetentionPolicy.SOURCE:注解保留到j(luò)ava編譯時(shí)期@Inherited可以被繼承
jdk動(dòng)態(tài)代理
- 被代理類必須實(shí)現(xiàn)一個(gè)接口,任意接口
public class Bus implements Runnable{}
- 創(chuàng)建一個(gè)類實(shí)現(xiàn)InvocationHandler,該類用來對(duì)象代理對(duì)象進(jìn)行方法的增強(qiáng)
public class TimeInvocation implements InvocationHandler{
private Object target;//被代理對(duì)象
public TimeInvocation(Object target){
this.target=target;
}
}
- 在invoke()方法中調(diào)用被代理對(duì)象的方法,并且添加增強(qiáng)的代碼
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long time1=System.currentTimeMillis();
//調(diào)用被代理對(duì)象的方法
method.invoke(target, args);
long time2=System.currentTimeMillis();
System.out.println(time2-time1);
return null;
}
通過Proxy.newProxyInstance(ClasLoader, Class, InvovationHandler)創(chuàng)建代理類對(duì)象
調(diào)用代理對(duì)象的方法
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){
//設(shè)置需要?jiǎng)?chuàng)建子類的類
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
//通過字節(jié)碼技術(shù)動(dòng)態(tài)創(chuàng)建子類實(shí)例
return enhancer.create();
}
//實(shí)現(xiàn)MethodInterceptor接口方法
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("前置代理");
//通過代理類調(diào)用父類中的方法
Object result = proxy.invokeSuper(obj, args);
System.out.println("后置代理");
return result;
}
}
public class DoCGLib {
public static void main(String[] args) {
CglibProxy proxy = new CglibProxy();
//通過生成子類的方式創(chuàng)建代理類
SayHello proxyImp = (SayHello)proxy.getProxy(SayHello.class);
proxyImp.say();
}
}
注意: jdk動(dòng)態(tài)代理與cglib的區(qū)別
jdk通實(shí)現(xiàn)接口的方式實(shí)現(xiàn)動(dòng)態(tài)代理 cglib通過繼承的方式實(shí)現(xiàn)動(dòng)態(tài)代理
jdk動(dòng)態(tài)代理與cglib如何選擇? CGLib創(chuàng)建的動(dòng)態(tài)代理對(duì)象性能比JDK創(chuàng)建的動(dòng)態(tài)代理對(duì)象的性能高不少,但是CGLib在創(chuàng)建代理對(duì)象時(shí)所花費(fèi)的時(shí)間卻比JDK多得多,所以對(duì)于單例的對(duì)象,因?yàn)闊o需頻繁創(chuàng)建對(duì)象,用CGLib合適,反之,使用JDK方式要更為合適一些。同時(shí),由于CGLib由于是采用動(dòng)態(tài)創(chuàng)建子類的方法,對(duì)于final方法,無法進(jìn)行代理。