1、目标对象必须实现接口 2、利用jdk的api,动态的在内存中构建代理对象 3、JDK代理也叫接口代理
//目标接口
public interface ITeach {
void study();
}
//目标类
public class Teach implements ITeach {
@Override
public void study() {
System.out.println("老师正在学习");
}
}
//代理类
public class DynamicProxy {
//目标对象
private Object target;
public DynamicProxy(Object target) {
this.target = target;
}
//为目标对象生产代理对象
public Object getProxyInstance(){
/**
* 1.指定当前目标对象使用的类加载器
* 2.目标对象实现的接口类型
* 3.事情处理,执行目标对象方法时,会触发事情处理器方法(会把当前执行的目标对象方法作为参数传入)
*/
return Proxy.newProxyInstance(DynamicProxy.class.getClassLoader(), target.getClass().getInterfaces(), (proxy, method, args) -> {
System.out.println("JDK动态代理开始");
Object result = method.invoke(target, args);
System.out.println("JDK动态代理结束");
return result;
});
};
}
public class Client {
public static void main(String[] args) {
ITeach teach = new Teach();
DynamicProxy proxy = new DynamicProxy(teach);
ITeach obj = (ITeach) proxy.getProxyInstance();
obj.study();
}
}
结果:
JDK动态代理开始
老师正在学习
JDK动态代理结束
ps:如果在Teach中添加方法,而ITeach中没有。生成代理对象强转为Teach就会报错。 故:代理只能代理接口中的方法,所以又叫接口代理。
1、目标对象可以不用实现接口 目标接口和目标类还是ITeach和Teach
public class CglibProxy implements MethodInterceptor {
//目标对象
private Object target;
public CglibProxy(Object target) {
this.target = target;
}
//为目标对象生产代理对象
public Object getProxyInstance(){
//创建一个工具
Enhancer enhancer = new Enhancer();
//设置父类
enhancer.setSuperclass(target.getClass());
//设置回调函数
enhancer.setCallback(this);
//创建代理对象
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("Cglib动态代理开始");
Object result = method.invoke(target, objects);
System.out.println("Cglib动态代理结束");
return result;
}
}
public class Client {
public static void main(String[] args) {
ITeach teach = new Teach();
CglibProxy proxy = new CglibProxy(teach);
Teach obj = (Teach) proxy.getProxyInstance();
obj.study();
}
}
结果:
Cglib动态代理开始
老师正在学习
Cglib动态代理结束