动态代理理解

动态代理

在这里插入图片描述

一、CGLIB动态代理

1、原理:利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理,CGLIB 通过动态生成一个需要被代理类的子类(即被代理类作为父类),该子类重写被代理类的所有不是 final 修饰的方法,并在子类中采用方法拦截的技术拦截父类所有的方法调用,进而织入横切逻辑。

package com.onlymark.proxy;

import com.onlymark.service.UserService;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * @auther Onlymark
 * @date 2021/5/7 上午6:05
 */
public class JavaProxyFactory1 implements MethodInterceptor {
	private UserService userService;

	public JavaProxyFactory1(UserService userService) {
		this.userService = userService;
	}

	//cglib
	public UserService createUserServiceProxy(){

		Enhancer enhancer = new Enhancer();
		//设置Enhancer对象的父类
		enhancer.setSuperclass(UserService.class);
		//设置回调方法
		enhancer.setCallback(this);
		//创建代理对象
		UserService service = (UserService)enhancer.create();
		//返回代理对象
		return service;
	}

	/**
	 * obj:cglib生成的代理对象 obj表示增强的对象,即实现这个接口类的一个对象;
	 * method:被代理对象方法 method表示要被拦截的方法;
	 * args:方法入参 args表示要被拦截方法的参数;
	 * methodProxy: 代理方法 proxy表示要触发父类的方法对象;
	 */
	@Override
	public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
		System.out.println("开启事务");
		Object object = method.invoke(userService, args);
		System.out.println("关闭事务");
		return object;
	}

	public static void main(String[] args) {
		JavaProxyFactory1 javaProxyFactory1 = new JavaProxyFactory1(new UserService());
		UserService userServiceProxy = javaProxyFactory1.createUserServiceProxy();
		userServiceProxy.adduser();

		userServiceProxy.deleteuser();
	}
}

一、动态代理

1.增强方法增强方法

package cn.tt.trendsProxy.JDKproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;


/**
 * @author Tzc
 * 这个类可以(自动生成代理类)
 * 实现方式:
 * 				 	1. 静态代理:有一个类文件描述代理模式
 * 				 	2. 动态代理:在内存中形成代理类
 * 						* 实现步骤:
 * 							1. 代理对象和真实对象实现相同的接口
 * 							2. 代理对象 = Proxy.newProxyInstance();
 * 							3. 使用代理对象调用方法。
 * 							4. 增强方法
 *
 * 						* 增强方式:
 * 							1. 增强参数列表
 * 							2. 增强返回值类型
 * 							3. 增强方法体执行逻辑
 */
@SuppressWarnings("all")
public class ProxyInvocationHandler implements InvocationHandler {
    //被代理的接口
    private Rent rent;
    public void setRent(Rent rent) {
        this.rent = rent;
    }

    //实现接口(抽象角色)生成得到代理类(处理程序方法生成我们要调用的接口对象)
   /*  public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
       newProxyInstance,方法有三个参数:
       loader: 用哪个类加载器去加载代理对象
       interfaces:动态代理类需要实现的接口
       h:动态代理方法在执行时,会调用h里面的invoke方法去执行*/
   /*
     getClass()取得当前对象所属的Class对象,通过getClass()方法得到该对象类Class后,可以通过Class获取这个类中的相关属性和方法
     getClassLoader()取得该Class对象的类装载器类装载器负责从Java字符文件将字符流读入内存,并构造Class类对象
     getClassLoader()把Class文件加载进内存封装为类对象
     getInterfaces()方法和Java的反射机制有关。它能够获得这个对象所实现的所有接口。

     三个参数:
                1. 类加载器:真实对象.getClass().getClassLoader()
                2. 接口数组:真实对象.getClass().getInterfaces()
                3. 处理器:new InvocationHandler()
   */
    public Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);
    }


    /*
        InvocationHandler 是代理实例的调用处理程序 实现的接口。
        每个代理实例都具有一个关联的调用处理程序。
        对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法。
    */
    /*
        proxy - 在其上调用方法的代理实例
        method - 对应于在代理实例上调用的接口方法的 Method 实例。Method 对象的声明类将是在其中声明方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。
        args - 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null。基本类型的参数被包装在适当基本包装器类(如 java.lang.Integer 或 java.lang.Boolean)的实例中。

        代理逻辑编写的方法:代理对象调用的所有方法都会触发该方法执行
            参数:
                1. proxy:代理对象
                2. method:代理对象调用的方法,被封装为的对象
                3. args:代理对象调用的方法时,传递的实际参数

    */
    //执行生成的代理类的方法,并返回结果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //动态代理的本质就是使用反射机制实现
             /* invoke方法参数:
                        obj - 从中调用底层方法的对象
                        args - 用于方法调用的参数
             */
        Object result = method.invoke(rent, args);
        //增强方法体执行逻辑
        seeHouse();
        hetong();
        fare();
        return result;

    }


    //看房
    public void seeHouse(){
        System.out.println("中介带我看房");
    }

    //签合同
    public void hetong(){
        System.out.println("签租赁合同");
    }

    //收中介费
    public void fare(){
        System.out.println("收中介费");
    }
}

2.增强参数

package cn.itcast.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyTest {

    public static void main(String[] args) {
        //1.创建真实对象
        Lenovo lenovo = new Lenovo();
        
        //2.动态代理增强lenovo对象
        /*
            三个参数:
                1. 类加载器:真实对象.getClass().getClassLoader()
                2. 接口数组:真实对象.getClass().getInterfaces()
                3. 处理器:new InvocationHandler()
         */
        SaleComputer proxy_lenovo = (SaleComputer) Proxy.newProxyInstance(lenovo.getClass().getClassLoader(), lenovo.getClass().getInterfaces(), new InvocationHandler() {

            /*
                代理逻辑编写的方法:代理对象调用的所有方法都会触发该方法执行
                    参数:
                        1. proxy:代理对象
                        2. method:代理对象调用的方法,被封装为的对象
                        3. args:代理对象调用的方法时,传递的实际参数
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                /*System.out.println("该方法执行了....");
                System.out.println(method.getName());
                System.out.println(args[0]);




*/
                //判断是否是sale方法
                if(method.getName().equals("sale")){
                    //1.增强参数
                    double money = (double) args[0];
                    money = money * 0.85;
                    System.out.println("专车接你....");
                    //使用真实对象调用该方法
                    String obj = (String) method.invoke(lenovo, money);
                    System.out.println("免费送货...");
                    //2.增强返回值
                    return obj+"_鼠标垫";
                }else{
                    Object obj = method.invoke(lenovo, args);
                    return obj;
                }



            }
        });

        //3.调用方法

       /* String computer = proxy_lenovo.sale(8000);
        System.out.println(computer);*/

        proxy_lenovo.show();
    }
}

3.增强返回值

package cn.itcast.web.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;

/**
 * 敏感词汇过滤器
 */
@WebFilter("/*")
public class SensitiveWordsFilter implements Filter {


    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //1.创建代理对象,增强getParameter方法

        ServletRequest proxy_req = (ServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //增强getParameter方法
                //判断是否是getParameter方法
                if(method.getName().equals("getParameter")){
                    //增强返回值
                    //获取返回值
                    String value = (String) method.invoke(req,args);
                    if(value != null){
                        for (String str : list) {
                            if(value.contains(str)){
                                value = value.replaceAll(str,"***");
                            }
                        }
                    }
                    
                    return  value;
                }

                //判断方法名是否是 getParameterMap

                //判断方法名是否是 getParameterValue

                return method.invoke(req,args);
            }
        });

        //2.放行
        chain.doFilter(proxy_req, resp);
    }
    private List<String> list = new ArrayList<String>();//敏感词汇集合
    public void init(FilterConfig config) throws ServletException {

        try{
            //1.获取文件真实路径
            ServletContext servletContext = config.getServletContext();
            String realPath = servletContext.getRealPath("/WEB-INF/classes/敏感词汇.txt");
            //2.读取文件
            BufferedReader br = new BufferedReader(new FileReader(realPath));
            //3.将文件的每一行数据添加到list中
            String line = null;
            while((line = br.readLine())!=null){
                list.add(line);
            }

            br.close();

            System.out.println(list);

        }catch (Exception e){
            e.printStackTrace();
        }

    }

    public void destroy() {
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值