@Override
public Object invoke(Objectproxy, Method method, Object[] args)throws Throwable {
System.out.println("调用"+method.getName() +"前");
Objectret = method.invoke(realObject, args);//在真实对象上调用方法,参数不变照传
System.out.println("调用"+method.getName() +"后");
return ret;//返回执行方法回的对象,为真实对象
}
});
System.out.println(hello);
hello.sayHi();//这里是真实对象调用方法了,可以输出"大家好!"
}
方式3:
publicclass TestProxy2implements InvocationHandler{
private ObjectrealObject;
/**
* @param realObject
* @return代理对象
*/
public Object createProxyObjectByJdk(ObjectrealObject) {
this.realObject = realObject;
return Proxy.newProxyInstance(realObject.getClass().getClassLoader(),realObject.getClass().getInterfaces(),this);
}
@Override
publicObject invoke(Objectproxy, Method method, Object[] args)throws Throwable {
System.out.println("调用"+method.getName() +"前");
Objectret = method.invoke(realObject, args);
System.out.println("调用"+method.getName() +"后");
returnret;
}
}
7.3使用CGLIB创建代理类
使用JDK自带的Proxy类不能创建没有实现接口的类的代理对象,这时就要用到第三方类库来创建了。如CGLIB。CGLIB是一个强大的,高性能,高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。(要加入jar包:cglib-nodep-xx.xx.jar)
使用CGLIB的Enhancer类来创建代理对象。
publicclass TestProxy {
@Test//创建类的代理对象
publicvoidtestCglibProxyClass() {
//真实对象,没有实现任何接口的类
final HelloImpl2readObject =new HelloImpl2();
Enhanceren = new Enhancer();
//设置回调函数
en.setCallback(newInvocationHandler() {
@Override
public Objectinvoke(Object proxy, Method method, Object[] args)throws Throwable {
returnmethod.invoke(readObject, args);//调用真实对象的方法并返回
}
});
en.setSuperclass(HelloImpl2.class);//设置父类
HelloImpl2hello2 = (HelloImpl2) en.create();//创建类的代理对象
hello2.sayHi();
}
@Test//创建接口的代理对象
publicvoidtestCglibProxyInterface() {
final IHello readObject=new HelloImpl();
Enhanceren = new Enhancer();
//设置回调函数
en.setCallback(newInvocationHandler() {
@Override
public Objectinvoke(Object proxy, Method method, Object[] args)throws Throwable {
returnmethod.invoke(readObject, args);//调用真实对象的方法并返回
}
});
en.setSuperclass(IHello.class);//设置父类
IHellohello = (IHello) en.create();//创建接口的代理对象
hello.sayHi();
}
}
7.4代理总结
spring在运行期创建代理,不需要特殊的编译器。
spring有两种代理方式:
1.若目标对象实现了若干接口,spring使用JDK的java.lang.reflect.Proxy类代理。
2.若目标对象没有实现任何接口,spring使用CGLIB库生成目标对象的子类。
使用该方式时需要注意:
1.对接口创建代理优于对类创建代理,因为会产生更加松耦合的系统。
对类代理是让遗留系统或无法实现接口的第三方类库同样可以得到通知,这种方式应该是备用方案。
2.标记为final的方法不能够被通知。spring是为目标类产生子类。任何需要被通知的方法都被复写,将通知织入。final方法是不允许重写的。