在介绍动态代理前先咱们先简单了解一下静态代理的概念
1.静态代理
巨星类
public class BigStar implements Star{ private String name ; public BigStar(String name) { this.name = name; } @Override public void sing() { System.out.println(name + "在唱歌"); } @Override public void dance() { System.out.println(name + "在跳舞"); } }
由巨星类抽象出的 巨星接口
public interface Star { public void sing(); public void dance(); }
代理类
public class proxy implements Star{ private Star star; public void setStar(Star star) { this.star = star; } @Override public void sing() { System.out.println("收费"); star.sing(); System.out.println("打扫场地"); } @Override public void dance() { System.out.println("收费"); star.dance(); System.out.println("打扫场地"); } }
静态代理执行
public static void main(String[] args) { //创建明星 BigStar star = new BigStar("ycy"); //创建代理类 proxy proxy_temp = new proxy(); //代理人代理明星 proxy_temp.setStar(star); //代理类执行sing 方法 调用明星的sing方法 proxy_temp.sing();
静态代理总结:本质上就是在原来的明星类上加了一层 这样就可以在不修改原来底层dao代码的基础上完成我们想要添加的任务。这样可以降低代码的耦合性 有利于我们维护代码的有效性。
2.动态代理
巨星类
public class BigStar implements Star{ private String name ; public BigStar(String name) { this.name = name; } @Override public void sing() { System.out.println(name + "在唱歌"); } @Override public void dance() { System.out.println(name + "在跳舞"); } }
由巨星类抽象出的 巨星接口
public interface Star { public void sing(); public void dance(); }
代理类工具
public class ProxyUtils { public static Star createProxy(BigStar bigStar){ //创建代理类 // ProxyUtils.class.getClassLoader(), 类加载器 // new Class[]{Star.class}, 代理类长什么样 // new InvocationHandler() 这是一个接口 我们用匿名内部类 实现这个接口里的invoke方法 Star proxy = (Star)Proxy.newProxyInstance(ProxyUtils.class.getClassLoader(), new Class[]{Star.class}, new InvocationHandler() { @Override //当代理类执行方法时 会执行invoke方法 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if(method.getName().equals("sing")){ System.out.println("准备演唱会----"); }else if(method.getName().equals("dance")){ System.out.println("准备舞蹈场地----"); }else { } return method.invoke(bigStar,args); } }); return proxy; } }
动态代理测试
BigStar ycy= new BigStar("杨超越"); System.out.println("----------------------------------"); Star proxy = ProxyUtils.createProxy(ycy); proxy.dance(); proxy.sing("好日子");
动态代理小结:
调用Proxy.newProxyInstance(ProxyUtils.class.getClassLoader(), new Class[]{Star.class}, new InvocationHandler())创建proxy代理对象 这其中我ProxyUtils.class.getClassLoader()为当前类的类加载器、 new Class[]{Star.class}表示我们要代理的接口长什么样 、new InvocationHandler()为我们需要重写里面的invoke方法
这个invoke方法就是在jdk动态代理类里加一层的关键,
public Object invoke(Object proxy, Method method, Object[] args)
这里的Object proxy代表我们要传入的被代理的对象, Method method表示方法对象(反射),Object[] args代表我们在调用代理类里的方法时传入的参数数组
代理类调用被代理类的过程(这里套用上面静态代理的说法):
1.创建明星(要被代理的对象)
2.使用工具创建代理人(经理人)
3.经理人调用自己的sing方法
proxy.sing("好日子");
-》 这个sing方法会调用invoke方法(实际上调用任意经理人的方法都会先调用invoke方法):
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if(method.getName().equals("sing")){ System.out.println("准备演唱会----"); }else if(method.getName().equals("dance")){ System.out.println("准备舞蹈场地----"); }else { } return method.invoke(bigStar,args); } --》在invoke方法里判断是哪个方法被调用了(利用反射method对象获取方法名)if(method.getName().equals("sing")){ System.out.println("准备演唱会----"); }else if(method.getName().equals("dance")){ System.out.println("准备舞蹈场地----"); }else { } -》调用明星中对应的方法(利用反射method对象调用明星的方法) method.invoke(bigStar,args);