代理分为两种:静态代理和动态代理
静态代理就不说了,基本上用不上,在SSM中也是动态代理
动态代理
目前我知道的动态代理分为两种:
- 基于JDK的动态代理:代理类和实体类要实现同一个接口
- 基于cglib的动态代理:代理类要继承实体类,第三方的
最后目的相同,代理实体类,做一些额外的工作
(1)基于JDK的动态代理
接口
public interface ForumService {
void removeTopic(int topicId);
void removeForum(int forumId);
}
实现类
public class ForumServiceImpl implements ForumService {
public void removeTopic(int topicId) {
System.out.println("模拟删除Topic记录:"+topicId);
}
public void removeForum(int forumId) {
System.out.println("模拟删除Forum记录:"+forumId);
}
}
代理类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JdkProxy implements InvocationHandler{
private ForumService fs;//定义实体类实现的接口,要一致
public JdkProxy(ForumService fs){ //构造方法,赋值给定义的接口变量
this.fs = fs;
}
//方法名随便定义,需要在new的时候执行这个方法,
public ForumService bind(){
return (ForumService) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{ForumService.class},this);
//看英文应该也明白,代理.新的代理实例化(这个Class载入,new Class[]{共同实现的接口.class},this)
}
//下面才是最重要的,执行程序,Cross实现的接口是带有Handler的,这个是头部的意思,相当于在你执行你需要的方法之前需要先执行这个
public Object invoke(Object arg0, Method method, Object[] obj2) throws Throwable {
// TODO Auto-generated method stub
if("removeForum".equals(method.getName())){ //看看你调用的方法是不是removeForum,是就代理执行,不是让它继续往下
System.out.println("代理删除");
}else{
method.invoke(fs,obj2); //这个是放过,让实体类自己去执行放过的方法
}
return null; //这个就是个形式, method.invoke这个是决定是否继续往下的关键
}
}
测试
public static void main(String[] args) {
ForumService target = new ForumServiceImpl();
ForumService f = new JdkProxy(target).bind();
f.removeForum(20);
f.removeTopic(30);
}
(2)基于cglib的动态代理
要导入cglib.jar才行
实体类
public class ForumServiceImpl {
public void removeTopic(int topicId) {
System.out.println("模拟删除Topic记录:"+topicId);
}
public void removeForum(int forumId) {
System.out.println("模拟删除Forum记录:"+forumId);
}
}
代理类
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 CglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz) {
enhancer.setSuperclass(clazz); //父类为clazz
enhancer.setCallback(this);
return enhancer.create(); //创建父类
}
//上面可以说是写死的,不像基于JDK的接口要换
//下面重点,,类带有Interceptor,就是拦截器类型的
public Object intercept(Object obj, Method method, Object[] args,MethodProxy proxy) throws Throwable {
if("removeForum".equals(method.getName())) {
System.out.println("代理删除");
}else {
return proxy.invokeSuper(obj, args); //方法放行,记住是invokeSuper,不是invoke,
//区别是一个是实体类,一个是实体类的子类,子类是我们创建的,方法放行后应该去实体类执行
}
return null; //这个就是一个形式,主要是 proxy.invokeSuper决定放不放行
}
}