目录
1、首先编写一个拥有增删改查方法的接口 CrudService
3、再写一个静态代理类来代理 CrudServiceImpl
1、首先编写一个拥有增删改查方法的接口 CrudService
3、再写一个动态代理类来代理 CrudServiceImpl
一、静态代理
代理类的作用是代理原本的类去做一些附加的事情。比如说,想要在每个代理的方法前都加上一个打印日志方法:如果去修改原代码的话不仅工作量巨大, 还容易破坏原代码的结构,很可能会导致出bug。而且工作中随意修改别人的代码是大忌。所以可以引出代理类的概念。
接下来演示一下实现静态代理的过程
1、首先编写一个拥有增删改查方法的接口 CrudService
public interface CrudService {
public void add();
public void delete();
public void update();
public void query();
}
2、再写一个实现类去实现它 CrudServiceImpl
public class CrudServiceImpl implements CrudService {
public void add() {
System.out.println("添加了一条数据");
}
public void delete() {}
public void update() {}
public void query() {}
}
3、再写一个静态代理类来代理 CrudServiceImpl
// 同样需要实现接口
public class JtDlProxy implements CrudService {
// 给代理类一个属性,为普通类
private CrudServiceImpl crudImpl;
// 代理类的构造方法
public void setCrudImpl(CrudServiceImpl crudImpl) {
this.crudImpl = crudImpl;
}
// 依旧需要实现接口的所有方法
public void add() {
// 执行切面处理(日志打印)
BeforeLog();
crudImpl.add();
}
public void delete() {}
public void update() {}
public void query() {}
// 用于切面加入的打印日志的方法
public void BeforeLog(){
System.out.println("执行方法前的日志");
}
}
4、编写一个main方法来调用
public static void main(String[] args) {
// 真实对象
CrudServiceImpl crudImpl = new CrudServiceImpl();
// 代理对象
JtDlProxy jtDlProxy = new JtDlProxy();
jtDlProxy.setCrudImpl(crudImpl);
// 通过代理对象来调用
jtDlProxy.add();
}
5、运行结果
在不改动原代码的情况下添加了日志方法,但是依旧显得很繁琐。
二、动态代理
代理类在程序运行时创建的代理方式被成为动态代理。相比于静态代理, 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法。 而且如果需要代理的类太多的话,对每一个类都需要写一个单独的代理类很麻烦,而用了动态代理只需要写一个动态生成代理类程序代码即可。
1、首先编写一个拥有增删改查方法的接口 CrudService
public interface CrudService {
public void add();
public void delete();
public void update();
public void query();
}
2、再写一个实现类去实现它 CrudServiceImpl
public class CrudServiceImpl implements CrudService {
public void add() {
System.out.println("添加了一条数据");
}
public void delete() {}
public void update() {}
public void query() {}
}
3、再写一个动态代理类来代理 CrudServiceImpl
其中的代码也可以作为通用模板去使用!
// 使用这个类,自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {
// 被代理的接口
private Object target;
public void setTarget(Object target) {
this.target = target;
}
// 生成代理对象
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
// 处理代理实例,并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
BeforeLog(method.getName()); // 通过反射调用方法名,来执行切面处理(日志打印)
// 反射(动态代理的本质就是反射)
Object result = method.invoke(target, args);
afterLog(); // 执行切面处理(日志打印)
return result;
}
// 用于切面加入的打印日志的方法
public void BeforeLog(String str){
System.out.println("执行"+str+"方法前的日志");
}
public void afterLog(){
System.out.println("执行后的日志");
}
}
4、编写一个main方法来调用
public static void main(String[] args) {
// 真实对象
CrudServiceImpl crudImpl = new CrudServiceImpl();
// 调用处理程序类的方法来生成代理对象,并调用接口方法
ProxyInvocationHandler pih = new ProxyInvocationHandler();
// 构造方法
pih.setTarget(crudImpl);
// 动态生成代理类
CrudService proxy = (CrudService) pih.getProxy();
// 利用代理类调用接口
proxy.add();
}
5、运行结果
这样就完成了一个动态代理的过程!