动态代理
动态代理的意义在于生成一个占位(代理对象),来代理真实对象,从而控制真实对象的访问。
理解(原理):代理对象是真实对象的代表,外部不需要知道代理对象的实现方式,只需要告诉代理对象想要干什么,代理对象依靠反射根据业务情况来进行处理。
动态代理一般执行过程:真实对象与代理对象绑定(获取代理对象),利用代理对象调用方法进行操作(实际是利用反射来调真实对象来操作)。
常见的动态代理;
JDk动态代理:
JDK动态代理必须要提供接口才能使用,在一些不能提供接口的环境中只能采用第三方技术。
JDK动态代理是java.lang.reflect.*包提供的方式。
重点代码:
//将真实对象与代理对象进行绑定,并返回代理对象。
Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
JDK动态代理的代理对象需要挂在接口下,故先声明一个接口。
public interface HelloWorld {
public void sayHelloWorld();
}
//实现接口,完成被代理类
public class HelloWorldImpl implements HelloWorld {
@Override
public void sayHelloWorld() {
System.out.println("Hello World");
}
}
//实现代理类
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);
}
/**
* 代理方法逻辑
*
* @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);// 相当于调用sayHelloWorld方法
System.out.println("在调度真实对象之后的服务");
return obj;
}
}
CGLIBLE动态代理:
// CGLIBLE动态代理可以通过其自带的加强类来生成代理对象
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.err.println("调用真实对象前");
// CGLIB反射调用真实对象方法
Object result = methodProxy.invokeSuper(proxy, args);
System.err.println("调用真实对象后");
return result;
}
}