代理的核心思想:
就是让真实角色帮助代理角色完成某种事情,真实角色专注于自己的事情
静态代理
最大的特点:真实角色和代理角色必须实现同一个接口
举一个实例:
需求:人都要结婚,需要让代理角色(婚庆公司)帮助我们每一个人完成结婚这件事情(婚礼)
1.首先要先创建一个结婚这个接口
interface Marry{ void marry(); }
2.创建真实角色You实现这个接口
class You implements Marry{ public void marry(){ System.out.println("结婚了"); } }
3.创建代理角色WeddingCompany实现这个接口
class WeddingCompany implements Marry{ private Marry marry;//声明接口类型 public WeddingCompany(Marry m){ this.marry=m; } public void marry(){ System.out.pringln("结婚前的准备"); if(marry!=null){ marry.marry(); } System.out.pringln("结婚后付尾款"); } }
4.测试类
class Demo{ public static void main(String[] args){ You you=new You();//先创建一个真实对象 WeddingCompany wc=new WeddingCompany(you); wc.marry(); } }
动态代理
jdk动态代理:
jdk提供的java.lang.reflect.Proxy通过反射,完成接口中方法的调用
前提条件:必须有接口
具有的静态功能:
public static Object newProxyInstance( ClassLoader loader, 当前接口的类加载器 Class<?>[] interfaces, 当前的代理的接口列表数组 InvocationHandler h) 代理的指派的处理程序 throws IllegalArgumentException
举一个例子:
有一个接口UserDao中有四种方法:
//针对用户的数据访问接口 public interface UserDao { /** * 添加 */ void add() ; /** * 修改 */ void update() ; /** * 删除功能 */ void delete() ; /** * 查询所有 */ void findAll() ; }
创建一个类实现这个接口即子实现类(代理角色)
//用户的接口实现 public class UserDaoImpl implements UserDao{ /** * 添加功能 */ @Override public void add() { System.out.println("添加了用户"); } /** * 修改功能 */ @Override public void update() { System.out.println("修改用户了"); } /** * 删除功能 */ @Override public void delete() { System.out.println("删除某个用户了"); } /** * 查询所有用户 */ @Override public void findAll() { System.out.println("查询所有用户"); } }
3,自定义一个类来实现InvocationHandler:代理的指派的处理程序
创建这个类的目的:调用接口中的方法
public class MyInvocationHandler implements InvocationHandler { private Object target ; //任意Java类型 (对真实角色) public MyInvocationHandler(Object target){ this.target = target ; } /** * * @param proxy 代理实例 * @param method 调用处理接口方法所在类对象Method(add()/update()/delelte()/findAll()) * @param args 实际参数 * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("权限校验"); //系统监控代码 //真实角色调用自己的方法 Object obj = method.invoke(target, args); // 调用这些方法,如果有返回值,返回Object(返回任意类型) System.out.println("产生日志");//系统监控代码 return obj; } }
4.测试类
public class Jdk_Proxy { public static void main(String[] args) throws Exception{ //前提接口:UserDao //接口多态 UserDao ud = new UserDaoImpl() ; //创建MyInvocationHandler MyInvocationHandler handler = new MyInvocationHandler(ud); UserDao ud3 = (UserDao) Proxy.newProxyInstance( ud.getClass().getClassLoader(), //通过字节码文件对象 调用 public Class<?>[] getInterfaces() ud.getClass().getInterfaces(), handler ); //代理实例 ud3.add(); System.out.println("=========="); ud3.update(); System.out.println("=========="); ud3.delete(); System.out.println("=========="); ud3.findAll(); } }