1、Spring Aop中使用到了动态代理技术,对于jdk动态代理,要求必须代理接口,底层是java的反射机制,对于类,使用cglib字节码增强来动态代理
2、设计模式中简单的代理模式实现
3、jdk动态代理的实现方法
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//实现了InvocationHandler接口并实现了它的invoke方法
public class ProxyTest implements InvocationHandler{
//目标代理对象
private Object target;
public ProxyTest(){
}
//带参的构造函数,用于传递目标代理对象
public ProxyTest(Object target){
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("执行方法前");
//代理对象执行对应的方法 在前面后后面都加上了代码,这是Aop的一种实现方式,面向切面编程
method.invoke(target, args);
System.out.println("执行方法后");
return target;
}
public static void main(String[] args) {
//创建需要被代理的对象
Sky sky1 = new ProxyTest().new SkyImpl();
//创建代理对象
ProxyTest proxyTest = new ProxyTest(sky1);
//生成代理对象
Sky sky = (Sky)Proxy.newProxyInstance(SkyImpl.class.getClassLoader(), SkyImpl.class.getInterfaces(),proxyTest );
//执行方法
sky.rain();
}
interface Sky{
void rain();
}
class SkyImpl implements Sky{
public void rain() {
System.out.println("天下雨了");
}
}
}
4、运行结果
5、反编译过后,实际上是代理类继承了Proxy类并且实现了对应代理的接口,由于java只能支持单继承,所以jdk代理只适用于代理接口,例如 $ProxyClass extends Proxy implements Sky
6、cglib动态代理案例,需要在maven中添加cglib的依赖包
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CglibTest {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
//设置需要代理的类
enhancer.setSuperclass(HelloServiceImpl.class);
//设置回调方法
enhancer.setCallback(new HelloMethodInterceptor());
//创建代理对象
HelloServiceImpl helloServiceImpl = (HelloServiceImpl)enhancer.create();
//调用代理对象的方法
helloServiceImpl.sayHello();
}
}
//被代理的类
class HelloServiceImpl{
public void sayHello(){
System.out.println("Hello,World!");
}
}
class HelloMethodInterceptor implements MethodInterceptor{
public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("方法调用前");
//执行代理对象的方法 在前面后面加通知都可以
methodProxy.invokeSuper(obj, args);
System.out.println("方法调用后");
return obj;
}
}
7、执行的结果
8、cglib是一种字节码增强的动态代理技术,它代理的是类,而具体的实现是代理类继承了需要被代理的类,并增强了它的方法 $ProxyClass extends HelloServiceImpl 注意:cglib不能代理final修饰的类,也不能代理final修饰的方法,因为不能重写