zoukankan      html  css  js  c++  java
  • 静态代理 和 JDK动态代理 迎客

    接口:UserManager.java

    1 package com.springdemo.manager;
    2
    3  public interface UserManager {
    4 public void add(String name,String password);
    5 public void delete(String name);
    6 public int count();
    7 } 

    类:UserManagerImpl.java

    代码
    1 package com.springdemo.manager;
    2
    3  public class UserManagerImpl implements UserManager {
    4
    5 public void add(String name, String password) {
    6 System.out.println(" do add user ... ");
    7 }
    8
    9 public void delete(String name) {
    10 System.out.println(" do delete user ... ");
    11 }
    12
    13 public int count() {
    14 return 10;
    15 }
    16 }

    问题:现要求在调用UserManager的每个方法时,都要检查操作员权限,但不能改变UserManagerImpl的代码。

    静态代理实现:

    静态代理类:UserManagerProxy.java

    代码
    package com.springdemo.manager;

    public class UserManagerProxy implements UserManager {

    private UserManagerImpl impl;

    public UserManagerProxy() {
    this.impl = new UserManagerImpl();
    }

    public void add(String name, String password) {
    checkPower();
    this.impl.add(name, password);
    }

    public void delete(String name) {
    checkPower();
    this.delete(name);
    }

    public int count() {
    checkPower();
    return this.impl.count();
    }

    private void checkPower() {
    System.out.println(
    "check manager power ....");
    }

    }

    这就是静态代理的思想。

    测试代码:

    代码
    1 package com.springdemo.client;
    2
    3  import com.springdemo.manager.UserManager;
    4  import com.springdemo.manager.UserManagerProxy;
    5
    6
    7  public class Client {
    8 public static void main(String[] args) {
    9 UserManager userManager = new UserManagerProxy();
    10 userManager.add("name..", "pwd..");
    11 }
    12
    13 }

    静态代理存在一个问题,比如,当我们在被代理的类中增加了一个方法,代理类中也要增加相应方法。

    为此,JDK中提供了动态代理接口。

    Jdk动态代理:

    我们只需要写一个自定义的调用处理器(实现接口java.lang.reflect.InvokationHandler),然后使用类java.lang.reflect.Proxy中的静态方法 newProxyInstance 来为需要被代理的类自动生成代理类(这个代理类是自动成得,不可见得),并把这个代理类当做原先的类使用即可。

    调用处理器类:UserManagerHandler.java

    代码
    1 package com.springdemo.manager;
    2
    3  import java.lang.reflect.InvocationHandler;
    4  import java.lang.reflect.Method;
    5
    6  public class UserManagerHandler implements InvocationHandler {
    7
    8 private Object target;
    9
    10 public UserManagerHandler(Object target){
    11 this.target = target;
    12 }
    13
    14 /**
    15 * (自动生成的)代理类将自动用这个方法这执行我们调用的方法。所以我们可以在这里插入我们想执行的代码。
    16 * 这个方法是代理类调用的,所以以下参数也是代理类传的。它们的分别是:
    17 * @param proxy 调用的代理类(就是自动生成的代理类的实例)
    18 * @param method 我们调用的方法
    19 * @param args 我们调用方法时传的参数
    20 */
    21 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    22 try{
    23 checkPower();
    24
    25 //这里会执行我们调用的方法,如果被调用方法没有返回值(void申明),这里返回null
    26   Object returnValue = method.invoke(target, args);
    27 return returnValue;
    28 }catch(Exception e){
    29 throw e;
    30 }
    31 }
    32
    33 private void checkPower() {
    34 System.out.println("check manager power ....");
    35 }
    36 }
    37  

    测试代码:

    代码
    1 package com.springdemo.client;
    2
    3  import java.lang.reflect.InvocationHandler;
    4  import java.lang.reflect.Proxy;
    5
    6  import com.springdemo.manager.UserManager;
    7  import com.springdemo.manager.UserManagerHandler;
    8  import com.springdemo.manager.UserManagerImpl;
    9
    10
    11  public class Client {
    12 public static void main(String[] args) {
    13 // UserManager userManager = new UserManagerProxy();
    14 // userManager.add("name..", "pwd..");
    15  
    16 UserManager userManager = new UserManagerImpl();
    17 ClassLoader loader = Client.class.getClassLoader();
    18 Class<?>[] interfaces = {UserManager.class};
    19 InvocationHandler h = new UserManagerHandler(userManager);
    20 userManager = (UserManager)Proxy.newProxyInstance(loader, interfaces, h);
    21 userManager.add("name..", "pwd..");
    22 userManager.count();
    23 }
    24
    25 }

    优化UserManagerHandler.java

    代码
    1 package com.springdemo.manager;
    2
    3  import java.lang.reflect.InvocationHandler;
    4  import java.lang.reflect.Method;
    5  import java.lang.reflect.Proxy;
    6
    7  public class UserManagerHandler implements InvocationHandler {
    8
    9 private Object target;
    10
    11
    12 // public UserManagerHandler(Object target){
    13 // this.target = target;
    14 // }
    15  
    16 public Object newProxy(Object target){
    17 this.target = target;
    18 return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    19 }
    20
    21 /**
    22 * (自动生成的)代理类将自动用这个方法这执行我们调用的方法。所以我们可以在这里插入我们想执行的代码。
    23 * 这个方法是代理类调用的,所以以下参数也是代理类传的。它们的分别是:
    24 * @param proxy 调用的代理类(就是自动生成的代理类的实例)
    25 * @param method 我们调用的方法
    26 * @param args 我们调用方法时传的参数
    27 */
    28 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    29 try{
    30 checkPower();
    31
    32 //这里会执行我们调用的方法,如果被调用方法没有返回值(void申明),这里返回null
    33   Object returnValue = method.invoke(target, args);
    34 return returnValue;
    35 }catch(Exception e){
    36 throw e;
    37 }
    38 }
    39
    40 private void checkPower() {
    41 System.out.println("check manager power ....");
    42 }
    43 }
    44  

    测试代码:

    代码
    1 package com.springdemo.client;
    2
    3  import com.springdemo.manager.UserManager;
    4  import com.springdemo.manager.UserManagerHandler;
    5  import com.springdemo.manager.UserManagerImpl;
    6
    7
    8  public class Client {
    9 public static void main(String[] args) {
    10 // UserManager userManager = new UserManagerProxy();
    11 // userManager.add("name..", "pwd..");
    12  
    13 UserManager userManager = new UserManagerImpl();
    14 UserManagerHandler h = new UserManagerHandler();
    15 userManager = (UserManager)h.newProxy(userManager);
    16 userManager.add("name..", "pwd..");
    17 userManager.count();
    18 }
    19
    20 }
    21  

    以这个动态代理的例子,说明一下Spring中AOP术语:

    1.切面(Aspect),对应UserMenagerHandler这个类。

    2.  连接点(JoinPoint),切面应用在某个方法上,这个方法就是连接点,如:UserManagerImpl类中的add()方法。

    3. 处理逻辑(Advice),对应UserMenagerHandler中的 checkPower() 方法。

     (处理逻辑(Advice)通常有:Before(前置通知),After(后置通知),Around(环绕通知),Throw(异常通知))

    4. 切点(PointCut),连接点的集合,审明处理逻辑在哪些方法上应用。

    5.  目标对象,对应UserManagerImpl的实例。

    6.  把Aspect应用到Manager的方法上,叫置入。

  • 相关阅读:
    pip安装requests时报 Requirement already satisfied: requests in d:pythonpyth... 的问题解决
    渗透测试靶场
    Spring Security核心类关系图
    Spring security 5 Authorize Configuration
    固定技术栈
    redis 指定端口 启动
    Spring 获取当前activeProfile
    通过进程编号 查询 监听端口
    lombok 插件安装
    idea 快捷键设置
  • 原文地址:https://www.cnblogs.com/pengxl/p/1915771.html
Copyright © 2011-2022 走看看