代理模式有三种不同的形式:静态代理、动态代理(JDK代理、接口代理)、CGLIB代理
目标:在不修改目标对象的前提下,对目标对象进行扩展。
需要定义接口或父类对象,被代理对象和代理对象通过实现相同的接口或继承相同的父类完成代理。
ITeacherDao作为实现接口,TeacherDao为目标对象实现了ITeacherDao接口,代理对象TeacherDaoProxy需要实现ITeacherDao接口,并且需要聚合目标对象。
它使代理对象不需要实现接口(但目标对象要实现接口),代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象。
interface ITeacherDao {
public void teach();
}
//**目标对象**
class TearcherDao implements ITeacherDao{
@Override
public void teach() {
System.out.println("teacher is teaching");
}
}
代理工厂:聚合目标对象,有生成代理对象的方法
这里简单介绍一下Proxy.newProxyInstance方法:
Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h);
loader:目标对象的类加载器
interfaces:目标对象的所有接口
InvocationHandler:函数调用时的处理接口
//工厂实现:
public class ProxyFactory {
ITeacherDao target;
public ProxyFactory(ITeacherDao iTeacherDao) {
this.target = iTeacherDao;
}
// 获取代理对象
public Object getInstance(){
//使用JDK动态生成代理对象
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 returnVal = method.invoke(target, args);
return returnVal;
}
});
}
}
测试方法:
public static void main(String[] args) {
ITeacherDao tearcherDao=new TearcherDao();
ProxyFactory proxyFactory = new ProxyFactory(tearcherDao);
Object instance = proxyFactory.getInstance();
ITeacherDao proxyObject= (ITeacherDao)instance;
proxyObject.teach();
}
无需目标对象实现接口,直接在内存中构建目标对象的子类对象,从而实现功能扩展。
底层通过框架ASM转换字节码并生成新的类。
注意:目标类不能是final类
TeacherDao(代理对象)不用继承接口,只需构建一个实现了MethodInterceptor接口的代理工厂对象,代理工厂对象聚合代理对象且需要实现interceptor方法用来实现方法的调用。
代码实例:
//代理对象,不用实现接口
public class TearcherDao {
public void teach() {
System.out.println("teacher is teaching");
}
}
//代理工厂,实现cglib包的MethodInterceptor接口
public class ProxyFactory implements MethodInterceptor {
TearcherDao target;//内聚代理对象
public ProxyFactory(TearcherDao teacherDao) {
this.target = teacherDao;
}
public TearcherDao getProxyInstance() {
//创建工具类
Enhancer enhancer = new Enhancer();
//工具类的父类为被代理对象
enhancer.setSuperclass(TearcherDao.class);
//设置回调函数
enhancer.setCallback(this);
return (TearcherDao) enhancer.create();
}
//拦截器控制方法实现
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("cglib代理");
Object invoke = method.invoke(target, args);
return invoke;
}
// 获取代理对象
}