静态代理

  1. interface play{
  2. void game(String name);
  3. void music();
  4. }
  5. class someone implements play{
  6. @Override
  7. public void game(String name) {
  8. System.out.println("玩游戏");
  9. }
  10. @Override
  11. public void music() {
  12. System.out.println("听音乐");
  13. }
  14. }
  15. class Proxyer implements play{
  16. private play player;
  17. public Proxyer(play player){
  18. this.player = player;
  19. }
  20. @Override
  21. public void game(String name) {
  22. System.out.println("代理人玩游戏---"+name);
  23. player.game("p");
  24. }
  25. @Override
  26. public void music() {
  27. System.out.println("代理人听音乐---");
  28. player.music();
  29. }
  30. }
  31. public class Main {
  32. public static void consumers(play p){
  33. p.game("s");
  34. p.music();
  35. }
  36. public static void main(String[] args) {
  37. consumers(new someone());
  38. consumers(new Proxyer(new someone()));
  39. // someone player = new someone();
  40. // Proxyer proxyer = new Proxyer(player);
  41. // proxyer.game();
  42. // proxyer.music();
  43. }
  44. }
  45. 代理人玩游戏---s
  46. 玩游戏
  47. 代理人听音乐---
  48. 听音乐

动态代理

  1. class ProxyHandler<T> implements InvocationHandler {
  2. private T proxy;
  3. public ProxyHandler(T proxy){
  4. this.proxy = proxy;
  5. }
  6. @Override
  7. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  8. System.out.println("代理人执行:" + method.getName() + "(), args: "+ Arrays.toString(args));
  9. return method.invoke(this.proxy,args);
  10. //要调用method方法名 proxied真正调用方法的实例 args要传入方法的参数
  11. }
  12. }
  13. public class DyProxy {
  14. public static void main(String[] args) {
  15. play one = new someone();
  16. play o = (play) Proxy.newProxyInstance(
  17. someone.class.getClassLoader(),
  18. someone.class.getInterfaces(),
  19. new ProxyHandler<>(one)
  20. );
  21. o.music();
  22. o.game("荒野大镖客");
  23. }
  24. }
  1. public class MainTest {
  2. public static void main(String[] args) {
  3. InvocationHandler handler = new InvocationHandler() {
  4. @Override
  5. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  6. System.out.println(method.getName());
  7. if (method.getName().equals("morning")) {
  8. System.out.println("Good morning, " + Arrays.toString(args));
  9. }
  10. return null;
  11. }
  12. };
  13. Object o = Proxy.newProxyInstance(
  14. Hello.class.getClassLoader(), // 传入ClassLoader
  15. new Class[]{Hello.class}, // 传入要实现的接口
  16. handler);// 传入处理调用方法的InvocationHandler
  17. ((Hello)o).morning("Bob",4);
  18. }
  19. }
  20. interface Hello {
  21. void morning(String name, int age);
  22. }
  23. //morning
  24. //Good morning, [Bob, 4]

在运行期动态创建一个interface实例的方法如下:

  1. 定义一个InvocationHandler实例,它负责实现接口的方法调用;
  2. 通过Proxy.newProxyInstance()创建interface实例,它需要3个参数:
    1. 使用的ClassLoader,通常就是接口类的ClassLoader;
    2. 需要实现的接口数组,至少需要传入一个接口进去;
    3. 用来处理接口方法调用的InvocationHandler实例。
  3. 将返回的Object强制转型为接口。

没有实现类,只用接口实现动态代理

  1. public interface UserMapper {
  2. int add(int a ,int b);
  3. static void main(String[] args) {
  4. final UserMapper proxyInstance = (UserMapper) Proxy
  5. .newProxyInstance(UserMapper.class.getClassLoader(), new Class[]{UserMapper.class},
  6. new InvocationHandler() {
  7. @Override
  8. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  9. System.out.println(method.getDeclaringClass());
  10. if (Object.class.equals(method.getDeclaringClass())) { //编程技巧,永远不会走if里面
  11. return method.invoke(this, "加运算执行");
  12. } else {
  13. int add = (int)args[0]+(int)args[1] ;
  14. return add ;
  15. }
  16. }
  17. });
  18. System.out.println(proxyInstance.add(3, 4));
  19. }
  20. }