JDK动态代理实现
-
1)创建一个接口:HelloWorld
package agency.jdk;
public interface HelloWorld {
void sayHelloWorld();
}
- 2)继承并实现接口中的方法:HelloWorldImpl
package agency.jdk;
public class HelloWorldImpl implements HelloWorld{
@Override
public void sayHelloWorld() {
System.out.println("Hello World !!");
}
}
- 3)创建一个类并实现InvocationHandler接口
package agency.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JdkProxyExample implements InvocationHandler{
//真实对象
private Object target = null;
/**
* 建立代理对象和真实对象的代理关系,并返回代理对象
* @param: target 真实对象
* @return:代理对象
public Object bind(Object target) {
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),this);
- 第一个参数:类加载器
- 第二个参数:把动理对象挂在哪个接口下
- 第三个参数:定义实现方法逻辑的代理类,this代表当前对象,它必须实现InvocationHandler接口的invoke方法,它就是代理逻辑方法的现实方法
}
/**
* @param proxy:代理对象
* @param method:当前调度方法
* @param args:当前方法参数
* @return 代理结果返回
* @throws Throwable:异常
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("进入代理逻辑方法");
System.out.println("在调度真实对象之前的服务");
Object obj = method.invoke(target,args);
System.out.println("在调度真实对象之后的服务");
return obj;
}
}
- 4)创建一个测试类
package agency.jdk;
public class TestJdkProxy {
public static void main(String[] args) {
JdkProxyExample jpe = new JdkProxyExample();
//绑定关系,因为挂在接口HelloWorld下,所以声明代理对象HelloWorld proxy
HelloWorld Hproxy = (HelloWorld) jpe.bind(new HelloWorldImpl());
//注意,此时HelloWorld对象已经是一个代理对象了,它会进入代理的逻辑方法invoke里
Hproxy.sayHelloWorld();
}
}
Cglib动态代理
- 1)准备jar包
- asm-3.3.1.jar
- asm-commons-6.0.jar
- asm-util-3.3.1.jar
- cglib-nodep-3.2.5.jar
- 2)创建一个真实对象
package agency.cglibdemo;
public class ReflectServiceImpl {
public void sayHello(String str) {
System.out.println("Hello "+str);
}
}
- 3)创建类并继承MethodInterceptor接口
package agency.cglibdemo;
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 CglibProxyExample implements MethodInterceptor{
/**
* 生成Cglib代理对象
* @param cls-Class类
* @return Class类的CGLIB代理对象
*/
public Object getProxy(Class cls) {
//设置CGLIB enhancer 增强类对象
Enhancer enhancer = new Enhancer();
//设置增强类型
enhancer.setSuperclass(cls);
//生成代理逻辑对象为当前对象,要求当前对象实现MethodInterceptor方法
enhancer.setCallback(this);
//生成并返回代理对象
return enhancer.create();
}
/**
* @param proxy 代理对象
* @param method 方法
* @param args 方法参数
* @param methodProxy方法代理
* @return 代理逻辑返回
* @throws Throwable 异常
*/
@Override
public Object intercept(Object proxy, Method method,
Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("调用真实对象之前");
//CGLIB反射调用真实对象方法
Object result = methodProxy.invokeSuper(proxy, args);
System.out.println("调用真实对象之后");
return result;
}
}
- 4)创建测试类
package agency.cglibdemo;
public class TestCglibProxy {
public static void main(String[] args) {
CglibProxyExample cpe = new
CglibProxyExample();
ReflectServiceImpl obj = (ReflectServiceImpl)
cpe.getProxy(ReflectServiceImpl.class);
obj.sayHello("张三");
}
}
JDK动态代理与Cglib的区别
- 前者是JDK自带的,后者是第三方提供的(在Sping中不需要自己导入jar包)
- 前者需要提供一个接口,后者不用
- 在sping中
- 如果目标对象实现了接口,默认情况下使用jdk动态代理
- 如果目标对象实现了接口,可以强制使用Cglib
- 如果目标对象没有实现接口,默认情况下使用Cglib