【javaSE】代理并不难

代理:

代理模式最主要的就是在不改变原来代码(就是目标对象)的情况下实现功能的增强

在学习AOP之前先了解代理,代理有两种:一种是动态代理,一类是静态代理。

静态代理

        相当于是自己写了一个代理类,在调用的时候调用的是代理类,代理类中的处理还是原生的处理逻辑,不过在前后添加上需要增强功能的代码。(类似继承实现的)

缺点:需要为每一个被代理的对象都创建一个代理类。

静态代理实现:

1.创建接口

public interface Target {
    public abstract String getExe();
}

2.实现目标对象

public class MyTarget implements Target {


    @Override
    public String getExe() {
        System.out.println("执行ing.....");
        return "ok";
    }
}

3.实现代理对象

package 反射;

public class Proxy implements Target{

    MyTarget myTarget;

    public Proxy(MyTarget myTarget) {
        this.myTarget = myTarget;
    }

    @Override
    public String getExe() {
        System.out.println("权限检查");
        String res= myTarget.getExe();
        System.out.println("日志打印");

        return res;

    }
}

4.测试代码

package 反射;


public class demo1 {

    public static void main(String[] args) {
        MyTarget myTarget=new MyTarget();
        Proxy proxy = new Proxy(myTarget);
        proxy.getExe();
    }


}

 

动态代理

动态代理模式最大的优势就是不用自己去写一个代理对象,它的代理对象会在java文件编译的时候,通过Java反射去创建的。所以减少了程序员的工作。动态代理的实现有两种方式,现在来介绍一下(基于接口实现)

jdk代理

1.创建接口

package com.aqiuo.jdk;

public interface UserDao {
        public void addUser();
        public void deleteUser();
}

2.创建实现类

package 代理;

public class UserServiceImpl implements UserService{

    public void addUser(){
        System.out.println("添加用户");
    }
    public void delUser(){
        System.out.println("删除用户");
    }

}

3.编写切面类

package 代理;

public class Aspect {
    public void admission(){
        System.out.println("权限检查");
    }
    public void log(){
        System.out.println("日志打印");
    }
}

4.编写代理类

package 代理;

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

public class JdkProxy implements InvocationHandler {
    //用Object型才能动态代理
    Object object;

    public Object createInstance(Object object){
        this.object=object;
        Class[] clazz = object.getClass().getInterfaces();
        ClassLoader classLoader=JdkProxy.class.getClassLoader();
        return Proxy.newProxyInstance(classLoader,clazz,this);

    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Aspect aspect=new Aspect();
        aspect.admission();
        Object res= method.invoke(object,args);
        aspect.log();

        return res;
    }
}

5.测试:

public class Test {
    public static void main(String[] args) {
        JdkProxy jdkProxy =new JdkProxy();
        UserService userService=new UserServiceImpl();
        UserService proxy= (UserService) jdkProxy.createInstance(userService);
        proxy.addUser();;
        proxy.delUser();

    }
}

/**JDK代理有一定局限性,使用动态代理的对象必须实现一个或多个接口,如果要对没有实现接口的类进行代理,可以用CGLIB代理

CGLIB代理

CGLIB是一个高性能的开源代码生成包,采用非常底层的字节码技术,对指定的目标类生成一个子类,并对子类增强,已经在Spring中集成

导包

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>2.2.2</version>
</dependency>

 MethodInterceptor拦截器
cglib的实现最重要的就是去实现这个MethodInterceptor接口来完成,就像jdk时候的InvocationHandler一样

package com.aqiuo.cglib;
//被代理的类
public class UserDao {
    
    public void addUser() {
        // TODO Auto-generated method stub
        System.out.println("添加用户");
    }

    public void deleteUser() {
        // TODO Auto-generated method stub
        System.out.println("删除用户");
    }

}

 实现代理类

//代理类
package com.aqiuo.cglib;

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import com.aqiuo.Aspect.MyAspect;

public class CglibProxy implements MethodInterceptor {
    
    //代理方法
    public Object createProxy(Object target) {
        //创建一个动态类对象
        Enhancer enhancer=new Enhancer();
        //确定要增强的类,设置为她的父类
        enhancer.setSuperclass(target.getClass());
        //添加回调函数
        enhancer.setCallback(this);
        //返回创建的代理类
        
        return enhancer.create();
    }
    
    /**
     * ProxyCGlib根据指定的父类,生成代理对象
     * method拦截的方法
     * args拦截方法的参数数组
     * methodProxy方法的代理对象,用来执行父类方法
     */
    

    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        //创建切面类对象
        MyAspect myAspect=new MyAspect();
        //前增强
        myAspect.check_permissions();
        //目标方法执行
        Object object=methodProxy.invokeSuper( proxy, args);
        //后增强
        myAspect.log();
        
        return object;
    }
    

}

        cglib的原理就是在运行的时候,cglib会自动去生成一个子类,在子类里面去完成增强操作(就是拦截器里面),这里我们来验证cglib就用保存它的子类来查验,也就是将它自动生成的类放在一个指定路径下去看。 


//测试类
package com.aqiuo.cglib;



public class CglibTest {
    public static void main(String[] args) {
        UserDao userDao=new UserDao();
        CglibProxy proxy=new CglibProxy();
        UserDao userDao2=(UserDao) proxy.createProxy(userDao);
        userDao2.addUser();
        userDao2.deleteUser();
    }

}

cglib动态代理原理:
①创建拦截器:继承MethodInterceptor的 intercepter的类,在拦截器中重写intercerpt( )方法,就是增强+目标对象的方法调用,返回拦截器

②在测试这边创建一个类似proxy的子类对象enhancer,然后设置这个代理对象的类型(setSuperclass(目标对象的类型.class完成))

③创建一个拦截器,enhancer通过去设置回调函数(setCallback(拦截器))

④创建代理对象enhancer.create(),代理对象的类型要和目标对象一致哈,然后通过代理对象去完成方法的调用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/282168.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

pandas将dataframe列中的list转换为多列

在应用机器学习的过程中&#xff0c;很大一部分工作都是在做数据的处理&#xff0c;一个非常常见的场景就是将一个list序列的特征数据拆成多个单独的特征数据。 比如数据集如下所示&#xff1a; data [[John, 25, Male,[99,100,98]],[Emily, 22, Female,[97,99,98]],[Michae…

JUC Lock 锁入门

文章目录 死锁&#xff08;Deadlock&#xff09;通过 Visualvm 等工具排查死锁 活锁park & unpark与 wait & notify 的区别park & unpark 实现&#xff1a;点外卖 Lock 对象ReentrantLock 可重入锁可重入lockInterruptibly 方法上锁&#xff08;可打断&#xff09;…

门诊病历系统教程,社区诊所电子处方系统软件操作教程

一、软件程序问答 门诊病历系统教程&#xff0c;社区诊所电子处方系统软件操作教程 1、电子处方软件在开处方时候&#xff0c;可以一键导入模板吗&#xff1f; 如下图&#xff0c;软件以 佳易王诊所电子处方软件V17.1为例说明 软件右侧点击 配方模板&#xff0c;只需输入症…

以太坊代币标准解读及相关Dapp的搭建

文章目录 什么是以太坊代币标准1、什么是以太坊2、以太坊代币标准 同质化代币 Dapp 搭建1、MetaMask 的安装2、Ganache 的安装3、实现 ERC-20 代币协议4、前端页面的编写5、部署流程及操作演示 什么是以太坊代币标准 1、什么是以太坊 以太坊&#xff08;Ethereum&#xff09;是…

2024年,程序员有哪些危机,有什么应对方式?

在2024年&#xff0c;程序员可能面临的危机主要包括技术更新迅速、职业竞争激烈、工作与生活平衡困难等方面。 为了应对这些危机&#xff0c;程序员可以采取以下策略&#xff1a; 技术更新迅速&#xff1a;随着技术的不断发展&#xff0c;新的编程语言和工具不断涌现&#xff…

52.网游逆向分析与插件开发-游戏反调试功能的实现-检测调试器

码云地址&#xff08;master分支&#xff09;&#xff1a;https://gitee.com/dye_your_fingers/sro_-ex.git 码云版本号&#xff1a;be9f058bfaaa4b015f2659db842e07ee37e58996 代码下载地址&#xff0c;在 SRO_EX 目录下&#xff0c;文件名为&#xff1a;SRO_Ex检测调试器.z…

迈向通用异常检测和理解:大规模视觉语言模型(GPT-4V)率先推出

PAPERCODEhttps://arxiv.org/pdf/2311.02782.pdfhttps://github.com/caoyunkang/GPT4V-for-Generic-Anomaly-Detection 图1 GPT-4V在多模态多任务异常检测中的综合评估 在这项研究中&#xff0c;我们在多模态异常检测的背景下对GPT-4V进行了全面评估。我们考虑了四种模式&#…

c 生成16×16像素点的rgb格式图片

想验证jpeg 编解码各个环节是否正确&#xff0c;特小尺寸的yuv格式图片找不到。特意用c代码生成一个1616像素点的rgb格式图片,再转换为yuv444格式&#xff0c;再88分割&#xff0c;余弦转换&#xff0c;量化&#xff0c;Z变换&#xff0c;霍夫曼编码&#xff0c;生成比特流&…

你真的懂Hello World!吗?(编译与链接,静态链接与动态链接)

&#x1f4ab;Hello World! 对于大家来说Hello World!应该是最熟悉不过的一句话&#xff0c;我们从Hello World!走进了计算机的世界&#xff0c;但是你真的了解Hello World!吗&#xff1f;你又思考过它背后蕴含的机理吗&#xff1f;他是怎么从代码变成程序的你真的思考过吗&…

react18框架笔记

React React 是 facebook 出的一款针对视图层的库(library)。它是基于单向数据流思想开发的&#xff0c;主要的一个功能就是针对视图显示&#xff0c;让我们把一个项目拆分成一个一个组件进行开发维护。 官网 目前我们讲的 react 是基于 18.2 的版本。react 每一个版本更新之…

谷歌Linux内核自动测试平台架构介绍-用自动测试测试难以测试的问题

1 摘要 内核和硬件等低级系统已被证明极难进行有效测试&#xff0c;因此&#xff0c;许多内核测试都是以手动为主方式进行的。现有的大多数测试框架都是为测试与底层平台隔离的高级软件而设计的&#xff0c;而底层平台被假定是稳定可靠的。测试底层平台本身需要一套全新的假设…

命令行万年历程序

在linux终端里看不了日历&#xff0c;我不答应&#xff01;代码仓库地址 一、命令行运行的效果图 如果输入的年份是目前所在年&#xff0c;会标注当天的日期 二、代码实现 1. 判断闰年 bool judge_leap_year(int year) {return ((year % 4 0) && (year % 100 ! 0)) …

听GPT 讲Rust源代码--src/tools(37)

File: rust/src/tools/clippy/clippy_lints/src/explicit_write.rs 在Rust源代码中&#xff0c;explicit_write.rs这个文件是Clippy的一个lint插件&#xff0c;其作用是检查代码中的write!、writeln!宏使用时的不当或繁琐的情况&#xff0c;并给出相关的警告或建议。 具体来说&…

浅谈冯诺依曼体系和操作系统

&#x1f30e;冯诺依曼体系结构 文章目录 冯诺依曼体系结构 认识冯诺依曼体系结构       硬件分类       各个硬件的简单认识         输入输出设备         中央处理器         存储器 关于内存 对冯诺依曼体系的理解 操作系统 操作系统…

关键字:try-catch关键字

在 Java 中&#xff0c;try-catch关键字用于异常处理。它们允许编写代码来捕获和处理异常&#xff0c;以确保程序能够在出现问题时合理地处理它们而不会崩溃。 以下是try-catch关键字的基本语法&#xff1a; 在try块中编写可能会抛出异常的代码。如果在try块中的任何代码抛出…

2024年【安全员-B证】考试报名及安全员-B证新版试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 安全员-B证考试报名考前必练&#xff01;安全生产模拟考试一点通每个月更新安全员-B证新版试题题目及答案&#xff01;多做几遍&#xff0c;其实通过安全员-B证考试试题很简单。 1、【多选题】《中华人民共和国消防法…

单字符检测模型charnet使用方法,极简

Git链接 安装按照上面的说明&#xff0c;说下使用。 把tools下面的test做了一点修改&#xff0c;可以读取一张图片&#xff0c;把里面的单个字符都检测和识别出来。 然后绘制到屏幕上。 import torch from charnet.modeling.model import CharNet import cv2, os import num…

搭建maven私服

maven maven简介 什么是maven&#xff1f; Maven这个单词来自于意第绪语&#xff08;犹太语&#xff09;&#xff0c;意为知识的积累。 Maven项目对象模型(POM)&#xff0c;可以通过一小段描述信息来管理项目的构建&#xff0c;报告和文档的项目管理工具软件。 Maven 除了以…

20231228在Firefly的AIO-3399J开发板的Android11使用Firefly的DTS配置单前后摄像头ov13850

20231228在Firefly的AIO-3399J开发板的Android11使用Firefly的DTS配置单前后摄像头ov13850 2023/12/28 19:20 缘起&#xff0c;突然发现只能打开前置的ov13850&#xff0c;或者后置的ov13850。 但是不能切换&#xff01; 【SDK&#xff1a;rk3399-android-11-r20211216.tar.xz】…

[Angular] 笔记 25:指令

组件指令 (chatgpt 回答) 在 Angular 中&#xff0c;组件本身可以被视为指令&#xff0c;这种指令被称为组件指令。组件是 Angular 应用的构建块之一&#xff0c;它封装了一段具有特定功能和特性的用户界面&#xff0c;并且可以在应用中重复使用。 组件指令具有以下特征&…