/***********************************
意义:生成一个代理对象来代理真实对象,管理真实对象的访问
1.代理对象和真实对象建立代理关系
2.实现代理对象的代理逻辑方法
包:java.lang.reflect.*
接口
public interface HelloWorld {
public void say();
}
实现类
public class HelloWorldImpl implements HelloWorld{
@Override
public void say() {
System.out.println("hello");
}
}
1:建立代理对象和真是服务对象的关系
2:实现代理逻辑
代理类如下:
public class JdkProxyExample implements InvocationHandler {
//真实的对象
private Object target = null;
/**
* 建立代理关系 返回代理对象
* @param target 真实对象
* @return 代理对象*/
public Object bind(Object target){
this.target = target;
//newProxyInstance包含三个参数:
//类加载器 生成的代理对象需要实现的接口 代理类
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("调度真实对象前的服务");
//invoke参数:
//代理对象(bind生成的) 当前调度的方法(反射实现) 调度方法的参数
Object obj = method.invoke(target,args);//相当于调用say
System.out.println("调度真实对象后的服务");
return obj;
}
}
客户端测试:
public class JdkProxyTest {
public static void main(String[] args){
JdkProxyExample obj = new JdkProxyExample();
//绑定
HelloWorld proxy = (HelloWorld)obj.bind(new HelloWorldImpl());
proxy.say();
}
}
JDK必须要提供接口才可以使用,但CGLIB只要一个非抽象类就可以实现动态代理
前提:导入cglib相关jar包
package reflect;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CGLIB implements MethodInterceptor {
/**
* 生成代理对象
* @param cls Class
* @return class类的代理对象*/
public Object getProxy(Class cls){
//enhancer增强类对象
Enhancer enhancer = new Enhancer();
//设置增强类型
enhancer.setSuperclass(cls);
//定义代理逻辑对象为当前对象,要求MehodInterceptor方法
enhancer.setCallback(this);
return enhancer.create();
}
/**
* 代理逻辑方法
* @param methodProxy
* @param proxy
* @param objects
* @param method
* @return 代理逻辑返回
* @throws Throwable*/
@Override
public Object intercept(Object proxy, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("调用前");
//cglib反射调用真实方法
Object res = methodProxy.invokeSuper(proxy,objects);
System.out.println("调用后");
return res;
}
}
隐藏了动态代理逻辑,供开发者直接实现
定义一个拦截器接口:
package Interceptor;
import java.lang.reflect.Method;
public interface Interceptor {
/**
* @param proxy 代理对象
* @param target 真实对象
* @param method 方法
* @param args 方法参数*/
public boolean before(Object proxy, Object target, Method method,Object[] args);//判断是否满足创建真实对象的条件
public void around(Object proxy, Object target, Method method,Object[] args);//false
public void after(Object proxy, Object target, Method method,Object[] args);//true
}
定义一个拦截器实现类:
package Interceptor;
import java.lang.reflect.Method;
public class MyInterceptor implements Interceptor{
@Override
public boolean before(Object proxy, Object target, Method method, Object[] args) {
System.out.println("反射前");
return false;
}
@Override
public void around(Object proxy, Object target, Method method, Object[] args) {
System.out.println("取代被反射的方法");
}
@Override
public void after(Object proxy, Object target, Method method, Object[] args) {
System.out.println("反射后");
}
}
在JDK动态代理中使用拦截器:
package Interceptor;
import javax.xml.transform.Result;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class InterceptorJdkProxy implements InvocationHandler {
private Object target;
private String interceptorClass = null;//拦截器全限定名
public InterceptorJdkProxy(Object target,String interceptorClass){
this.target = target;
this.interceptorClass = interceptorClass;
}
/**
* 绑定委托对象并返回一个代理占位
* @param target 真实对象
* @return 代理对象*/
public static Object bind(Object target,String interceptorClass){
//取得代理对象
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InterceptorJdkProxy(target,interceptorClass));
}
/**
* 通过代理对象调用方法,首先进入
* @param proxy 代理对象
* @param method
* @param args
* @return 代理对象*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//判断拦截器
if(interceptorClass == null){
return method.invoke(target,args);
}
Object res = null;
//通过反射生成拦截器
Interceptor interceptor =(Interceptor)
Class.forName(interceptorClass).newInstance();
//前置方法
if (interceptor.before(proxy,target,method,args)){
//反射原有方法
res = method.invoke(target,args);
}else {
//代理失败,around
interceptor.around(proxy,target,method,args);
}
//代理生效,after
interceptor.after(proxy,target,method,args);
return res;
}
}
测试
public static void main(String[] args){
HelloWorld proxy = (HelloWorld)
InterceptorJdkProxy.bind(new HelloWorldImpl(),
"Interceptor.MyInterceptor");
proxy.say();
}
本博客大部分内容来自
[Java EE互联网轻量级整合开发SSM框架和Redis实现] --杨开阵,周吉文,梁华辉等.
中国公信出版社,电子工业出版社