1)jdk Proxy.newInstance(ClassLoader loader,Interface[] interfaces,Class clazz);
這種方法主要是代理接口,不能代理類。
第一步實現invocationHandler接口
public class Proxy implements InvocationHandler{
private TestInterface object;
public Proxy(TestInterface testItf){
this.object = testItf;
}
public PersonAction getInstace(){
return (TestInterface) Proxy.newProxyInstance(this.getClass().getClassLoader(),new Class[]{TestInterface.class},this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("args are "+method.getName());
// 在調用實際方法之前可以做很多前置操作
return method.invoke(pa,args);
}
}
然後就是寫一個TestInterface的接口和兩個實現了該接口的實現類,
public interface TestInterface {
void bigAct();
}
public class Programmer implements TestInterface {
public void bigAct(){
println("i do program every day.i can be a great programmer.");
}
}
public class Dancer implements TestInterface {
public void bigAct(){
println("i dance every day.i can be a great dancer.");
}
}
測試代理類
public class ActionMain {
public static void main(String[] args) {
Programmer p2 = new Programmer();
TestInterface p = new Proxy(p2).getInstace();
p.bigAct();
//這裏看到p2注入到Proxy中,並返回了一個Instance對象,然後再執行p的bigAct方法。
//具體Proxy.newInstance()實現是通過
//class.getConstructor().newInstance(Invocationhandler);
//即 ConstructorAccessor.newInstance(Object[] var1);
//我們可以在調用具體的方法前,做很多前置或者是後置操作,這也是aop的思想。
}
}
public interface ConstructorAccessor {
Object newInstance(Object[] var1) throws InstantiationException, IllegalArgumentException, InvocationTargetException;
}
2)CGLib動態代理
第一步實現代理類
public class ProxyCglib implements MethodInteceptor{
Object obj;
public Object newInstance(Object object){
this.obj = object;
Enhancer enhancer = new Enhancer();
enhancer.setCallback(this);
enhancer.setSuperClass(object.getClass());
return enhancer.create();
}
@Override
public void intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)throws Throwable {
return method.invoke(obj,args);//兩種方式都是通過反射來實現方法的調用。
}
}
和jdk動態代理的區別就是cglib可以代理類,而jdk只能代理接口,如果沒有實現接口,就代理不了,springboot動態代理自動在兩者之間切換,如果類實現了接口就用cglib如果沒有就用cglib。當然cglib動態代理還要引入asm的jar包。