静态代理模式
静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象需要一起实现相同的接口或者是继承相同的父类。
案例:教师教书,在teach()方法前后分别做额外的处理
类图如下:
接口:
public interface ITeacherDao {
public void teach();
}
实现类:
public class TeacherDao implements ITeacherDao {
@Override
public void teach() {
System.out.println("教师教书");
}
}
代理类:
public class TeacherDaoProxy implements ITeacherDao {
private ITeacherDao teacherDao;
public TeacherDaoProxy(ITeacherDao teacherDao) {
this.teacherDao = teacherDao;
}
@Override
public void teach() {
System.out.println("前处理");
teacherDao.teach();
System.out.println("后处理");
}
}
客户端测试类:
public class Client {
public static void main(String[] args) {
//创建目标对象
TeacherDao teacherDao = new TeacherDao();
//创建代理对象
TeacherDaoProxy teacherDaoProxy = new TeacherDaoProxy(teacherDao);
teacherDaoProxy.teach();
}
}
缺点:一旦接口中增加方法,目标对象与代理对象都要维护
动态代理
1)在动态代理中,代理对象不需要实现接口,但是目标对象要实现接口,否则不能用动态代理
2)代理对象的生成,利用JDK中的反射机制,动态的在内存中构建代理对象
3)JDK实现代理只需要使用newProxyInstance方法,需要接收三个参数:
ClassLoader、Interfaces 以及InvocationHandler
接口:
public interface ITeacherDao {
public void teach();
}
实现类:
public class TeacherDao implements ITeacherDao {
@Override
public void teach() {
System.out.println("教师教书中");
}
}
代理工厂类:
public class ProxyFactory {
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
public Object getProxyInstance(){
return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("处理前");
Object invokeVal = method.invoke(target, args);
System.out.println("处理后");
return invokeVal;
}
});
}
}
客户端测试类:
public class Client {
public static void main(String[] args) {
//创建目标对象
ITeacherDao teacherDao = new TeacherDao();
//创建代理对象
ProxyFactory proxyFactory = new ProxyFactory(teacherDao);
ITeacherDao instance = (ITeacherDao) proxyFactory.getProxyInstance();
instance.teach();
}
}
代理模式-Cglib
Cglib代理也叫作子类代理,不需要实现某个类。
目标类:
package com.atguigu.proxy.cglib;
public class TeacherDao {
public void teach() {
System.out.println(" 老师授课中 , 我是cglib代理,不需要实现接口 ");
}
}
代理工厂类:
实现MethodInterceptor接口,重写intercept方法
package com.atguigu.proxy.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 ProxyFactory implements MethodInterceptor {
//维护一个目标对象
private Object target;
//构造器,传入一个被代理的对象
public ProxyFactory(Object target) {
this.target = target;
}
//返回一个代理对象: 是 target 对象的代理对象
public Object getProxyInstance() {
//1. 创建一个工具类
Enhancer enhancer = new Enhancer();
//2. 设置父类
enhancer.setSuperclass(target.getClass());
//3. 设置回调函数
enhancer.setCallback(this);
//4. 创建子类对象,即代理对象
return enhancer.create();
}
//重写 intercept 方法,会调用目标对象的方法
@Override
public Object intercept(Object arg0, Method method, Object[] args, MethodProxy arg3) throws Throwable {
System.out.println("Cglib代理模式 ~~ 开始");
Object returnVal = method.invoke(target, args);
System.out.println("Cglib代理模式 ~~ 提交");
return returnVal;
}
}
客户端测试类:
package com.atguigu.proxy.dynamic;
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
//创建目标对象
ITeacherDao target = new TeacherDao();
//给目标对象,创建代理对象, 可以转成 ITeacherDao
ITeacherDao proxyInstance = (ITeacherDao)new ProxyFactory(target).getProxyInstance();
// proxyInstance=class com.sun.proxy.$Proxy0 内存中动态生成了代理对象
System.out.println("proxyInstance=" + proxyInstance.getClass());
//通过代理对象,调用目标对象的方法
//proxyInstance.teach();
proxyInstance.sayHello(" tom ");
}
}