07_注解与动态代理

Spring动态代理与AOP 通过上述步骤,Spring能够通过动态代理技术,在目标方法执行之前自动调用@Before通知中的方法,实现程序的模块化、可维护性和可扩展性。这样的机制使得开发者能够专注于核心业务逻辑,而不需要在每一处方法调用中编写重复的前置检查代码。实际上,当你在方法上使用注解时,Spring会确保该方法被代理,使其能够正确地管理事务。这个代理过程是基于Spring的AOP机制,并且是在运行时动态生成的,无需开发者在类定义或方法声明中添加额外的代码。 阅读详情

注解

什么是注解
  • 注解(Annotation),就是 Java 代码里面的特殊标记,例如 @Override、@Test 等
  • 作用:让其他程序根据注解信息来决定怎么执行该程序
  • 注意:注解可以用在类上、构造器上、方法上、成员变量上、参数上…
  • 注解的本质是一个接口,Java 中所有注解都是继承了 Annotation 接口的
  • @注解(…) 其实就是一个实现类对象,实现了该注解以及 Annotation 接口
自定义注解
// 自定义注解
public @interface MyTest {
    String aaa();

    boolean bbb() default true;

    String[] ccc();
}
// 方法部分
@MyTest(aaa = "Jack", ccc = {"Java", "HTML"})
public void run() {}

特殊属性名:value——如果注解中只有一个 value 属性,使用注解时,value 名称可以不写!

public @interface MyTest {
    String value();  // 特殊属性
}
public @interface MyTest {
    String value();  // 特殊属性
    int age() default 23;  // 当有默认值时候,可以不删除此行
}
@MyTest("Jack")
public void run() {}
元注解
  • 元注解指的是:修饰注解的注解
@Target(ElemeElenntType.TYPE)作用:声明被修饰的注解只能在哪些位置使用
TYPE类,接口
FIELD成员变量
METHOD成员方法
PARAMETER方法参数
CONSTRUCTOR构造器
LOCAL_VARIABLE局部变量
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

@Target({ElemeElenntType.TYPE,ElementType.METHOD})  // 当前被修饰的注解只能用在类和成员方法上
public @interface MyTest {
}
@Retention(RetentionPolicy.RUNTIME)作用:声明注解的保留周期
SOURCE只作用在源码阶段,字节码文件中不存在
CLASS(默认值)保留到字节码文件阶段,运行阶段不存在
RUNTIME(开发常用)一直保留到运行阶段
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE, ElementType.METHOD})  // 当前被修饰的注解只能用在类和成员方法上
@Retention(RetentionPolicy.RUNTIME)  // 控制下面的注解一直保留到运行时
public @interface MyTest {
}
注解的解析

什么是注解的解析?

  • 就是判断类上、方法上、成员变量上是否存在注解,并把注解里的内容给解析出来

如何解析注解?

  • 思想:要解析谁上面的注解,就应该先拿到谁
// 自定义注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest {
    String value();
    double aaa() default 100;
    String[] bbb();
}
// 在类和方法上使用注解

@MyTest(value = "Jack", aaa = 99.8, bbb = {"Java", "HTML"})
public class Demo {
    public static void main(String[] args) {}

    @MyTest(value = "Tony", aaa = 88.6, bbb = {"java", "html"})
    public void run() {}
}
// 解析类上的注解

import org.junit.Test;
import java.util.Arrays;
public class AnnotationTest {
    @Test
    public void parseClass() {
        // 1. 先得到 Class 对象
        Class c = Demo.class;
        
        // 2. 解析类上的注解
        // 判断这个类上是否包含了某个注解
        if (c.isAnnotationPresent(MyTest.class)) {
            MyTest myTest = (MyTest) c.getDeclaredAnnotation(MyTest.class);
            System.out.println(myTest.value());
            System.out.println(myTest.aaa());
            System.out.println(Arrays.toString(myTest.bbb()));
        }
    }
}
/*
运行结果:
    Jack
    99.8
    [Java, HTML]
 */
// 解析方法上的注解

import org.junit.Test;
import java.lang.reflect.Method;
import java.util.Arrays;

public class AnnotationTest {
    @Test
    public void parseMethod() throws Exception {
        // 1. 先得到 Class 对象,然后通过 Class 对象获取方法对象
        Class c = Demo.class;
        Method m = c.getDeclaredMethod("run");

        // 2. 解析方法上的注解
        // 判断这个方法上是否包含了某个注解
        if (m.isAnnotationPresent(MyTest.class)) {
            MyTest myTest = (MyTest) m.getDeclaredAnnotation(MyTest.class);
            System.out.println(myTest.value());
            System.out.println(myTest.aaa());
            System.out.println(Arrays.toString(myTest.bbb()));
        }
    }
}
/*
运行结果:
    Tony
    88.6
    [java, html]
 */
应用场景

案例:模拟 Junit 框架

// 需求:定义若干个方法,只要加了MyTest注解,就会触发该方法的执行
/*  分析:
	 1.定义一个自定义注解 MyTest,只能注解方法,存活范围是一直都在
	 2.定义若干个方法,部分方法加上 @MyTest 注解修饰,部分方法不加
	 3.模拟一个 Junit 程序,可以触发加了 @MyTest 注解的方法执行
*/
// 自定义注解部分

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)  // 注解只能注解方法
@Retention(RetentionPolicy.RUNTIME)  // 让当前注解可以一直存活着
public @interface MyTest {}
// 模拟框架部分

import java.lang.reflect.Method;

public class AnnotationTest {

    public void test1() {
        System.out.println("===test1===");
    }

    @MyTest
    public void test2() {
        System.out.println("===test2===");
    }

    public void test3() {
        System.out.println("===test3===");
    }

    @MyTest
    public void test4() {
        System.out.println("===test4===");
    }

    public static void main(String[] args) throws Exception {
        AnnotationTest a = new AnnotationTest();
        // 启动程序!
        // 1. 得到 Class 对象
        Class c = AnnotationTest.class;

        // 2. 提取这个类中的全部成员方法
        Method[] methods = c.getDeclaredMethods();

        // 3. 遍历,获取到每个方法对象,看看其方法上是否存在 @MyTest 注解
        // 如果存在,则触发该方法执行
        for (Method method : methods) {
            if (method.isAnnotationPresent(MyTest.class)) {
                method.invoke(a);  // 触发当前方法执行
            }
        }
    }
}
/*
运行结果:
    ===test2===
    ===test4===
 */

动态代理

代理:将一些通用部分的代码提取出来,交给代理去实现(类比 Python 的装饰器)
// 创建一个明星类(前置工作)

// 明星(类)
public class Star implements Agent {
    private String name;

    public Star(String name) {
        this.name = name;
    }
    
    // 唱歌方法
    public String sing(String title) {
        System.out.println(this.name + "正在唱" + title);
        return "Think everyone!";
    }
    
    // 跳舞方法
    public void dance() {
        System.out.println(this.name + "正在跳舞");
    }
}
// 创建一个代理人接口(前置工作)

// 代理人(接口)
public interface Agent {
    String sing(String name);
    void dance();
}
// 创建一个工具类,即:能制作出"代理人"的公司(前置工作)

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

// 中介公司(类)
public class ProxyUtil {
    // 创建代理对象的静态方法
    public static Agent createProxy(Star sss) {
        /*
        public static Object newProxyInstance(ClassLoader loader,
                                              Class<?>[] interfaces,
                                              InvocationHandler h)
              参数一:用于指定一个类加载器
              参数二:指定生成的代理长什么样子,也就是有哪些方法
              参数三:用来指定生成的代理对象要干什么事情
        */
        Agent starProxy = (Agent) Proxy.newProxyInstance(
                ProxyUtil.class.getClassLoader(),  // 参数一
                new Class[]{Agent.class},  // 参数二
                new InvocationHandler() {  // 参数三
                    @Override  // 回调方法
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // 代理对象要做的事情,请在这里写代码
                        if (method.getName().equals("sing")) {
                            System.out.println("准备话筒,收钱20W");
                        } else if (method.getName().equals("dance")) {
                            System.out.println("准备场地,收钱99W");
                        }
                        return method.invoke(sss, args);
                    }
                });
        return starProxy;  // 本静态方法的最后是————返回创建好的"代理对象"
    }
}
// 调用工具类,让公司为某个明星对象去定制一个专属代理人(正式部分)

public class Test {
    public static void main(String[] args) {
        // 创建一个明星,叫"迈克尔-杰克逊"
        Star star = new Star("Michael-Jackson");
        // 为"迈克尔-杰克逊"创建一个代理人
        Agent agent = ProxyUtil.createProxy(star);

        System.out.println(agent.sing("新年好"));  // 让代理人安排他唱歌
        System.out.println("-----------------");
        agent.dance();  // 让代理人安排他跳舞
    }
}

/* 运行结果:
    准备话筒,收钱20W
    Michael-Jackson正在唱新年好
    Think everyone!
    -----------------
    准备场地,收钱99W
    Michael-Jackson正在跳舞
 */
拆解一个带主动均衡的BMS模块:从变压器、MOS管矩阵到控制逻辑,图文详解内部设计与成本构成 本文深度拆解了一款带主动均衡功能的BMS模块,详细解析了其核心架构、元器件选型与成本构成。通过高频变压器、MOS管矩阵等硬件设计,该模块实现了高达87%的能量转移效率,远超普通被动均衡方案。文章还揭示了汽车级PCB设计、软件策略优化等关键技术细节,为锂电池管理系统设计提供了实用参考。 阅读详情

相关推荐

基于Python适用于YOLO目标检测算法的图片数据增强处理

为了增强模型的鲁棒性以及数据的丰富性,同 时为了防止由于数据过少发生过拟合,本设计对数 据集进行数据增强处理,包括随机亮度调节、随机 对比度调节、随机饱和度调节、加入高斯噪声、水 平翻转、运动模糊和旋转 15°

weixin_67136409的博客 699

基础复习(反射、注解、动态代理)

反射,注解,动态代理

qq_50952157的博客 668

格拉姆角场(GAF)实战:用Python实现时间序列图像化处理

本文深入解析了格拉姆角场(GAF)技术,这是一种将一维时间序列转化为二维图像特征的方法,以便利用卷积神经网络(CNN)等图像模型进行深度分析。文章通过Python实战代码,详细演示了GASF和GADF两种核心转换的实现过程,并探讨了其在时序数据分类任务中的应用,为故障预警、金融模式识别等场景提供了强大的图像驱动分析视角。

weixin_29079671的博客 273

Spring AOP切面编程 IOC DI注解 代理模式

Java 动态代理是使用 java.lang.reflect 包中的 Proxy 类与 InvocationHandler 接口这两个来完成的。要使用 JDK 动态代理,真实类必须实现接口。JDK 动态代理将会拦截所有 pubic 的方法(因为只能调用接口中定义的方法),这样即使在接口中增加了新的方法,不用修改代码也会被拦截。动态代理的最小单位是类(类中某些方法都会被处理),如果只想拦截一部分方法,可以在 invoke 方法中对要执行的方法名进行判断。代理类与真实类共同实现一个接口的。

m0_63600788的博客 654

超详细 Git创建仓库及上传项目至Github操作(Windows系统)

文章目录前言一、Git下载及安装二、创建代码仓库1.配置身份2.创建本地仓库3.提交本地代码三、使用Git上传代码至Github1.创建ssh keys2.在Github中新建仓库3.关联本地仓库与Github仓库4.推送代码至Github仓库总结 前言 本文对于Windows系统上git的安装及基本使用方法进行简单介绍,并介绍如何使用git将仓库中的项目上传至个人的Github中去。内容参考《第一行代码》以及一些博客。 本文适合新手阅读哦~ 一、Git下载及安装 打开网站 git下载 下载安装包(直接

lijianyi0219的博客 2万+

YOLOv8 轴承缺陷检测 使用YOLOv8进行训练、评估和可视化预测结果 包含1440张图片的轴承缺陷检测数据集 YOLO格式或XML格式

本文介绍了一个基于YOLOv8的轴承缺陷检测项目。数据集包含1440张图片,标注了4类缺陷(凹槽、凹陷、卡伤、划痕),按8:1:1比例划分为训练集(1152张)、验证集(144张)和测试集(144张)。标注文件支持YOLO格式和XML格式,可直接用于模型训练。项目实现了数据准备、模型训练、评估及可视化预测结果的全流程,使用YOLOv8n预训练模型进行50个epoch的训练,并提供了数据格式转换(XML转YOLO)的代码示例。最终模型可自动检测轴承表面缺陷,并保存预测结果。

OICQQ67658008的博客 1438

如何修改注解里面的属性值

如何修改注解里面的属性值

小何的博客 1636

【芯片驱动】2. CMT2300A配合硬件测试(灵敏度和发射功率)的软件实现

前言 在开发一款无线射频产品的时候,软件是一部分,硬件也是一部分。而决定无线收发性能的,首先是硬件的匹配电路,然后才到软件部分的优化。 一款无线射频产品,首先需要先决定是在那个频率范围内(当然是国家允许的范围内),然后硬件则需要在基于这个频点范围进行硬件的参数匹配,具体又分为发送功率匹配、天线匹配、和接收灵敏度的匹配。 现在我们使用2300a这款无线芯片来说,除非自己的团队是射频专家,则可以自己进行无线外围电路的设计外,另外一种更加快捷的方式,就是寻找原厂技术支持,他们会给...

sishuihuahua的博客 7052

Mybatis07、使用注解开发

大家之前都学过面向对象编程,也学习过接口,但在真正的开发中,很多时候我们会选择面向接口编程根本原因 : 解耦 , 可拓展 , 提高复用 , 分层开发中 , 上层不用管具体的实现 , 大家都遵守共同的标准 , 使得开发变得容易 , 规范性更好关于接口的理解三个面向区别面向对象是指,我们考虑问题时,以对象为单位,考虑它的属性及方法 .面向过程是指,我们考虑问题时,以一个具体的流程(事务过程)为单位,考虑它的实现 .接口设计与非接口设计是针对复用技术而言的,与面向对象(过程)不是一个问题.更多的体现就是对系统整体

林知屿的博客 670

Qt和FFmpeg的视频压缩工具

m_progressDialog = new QProgressDialog("正在压缩视频...", "取消", 0, 100, parent);QString file = QFileDialog::getOpenFileName(this, "选择视频文件", "",QString file = QFileDialog::getSaveFileName(this, "保存压缩文件", "",QMessageBox::warning(parent, "错误", "请设置输入和输出文件路径");

寒寒豆豆软件公司的博客 101

华为OD机试E卷 -猜字谜(Java & Python& JS & C++ & C )

小王设计了一个简单的猜字谜游戏,游戏的谜面是一个错误的单词,比如nesw,玩家需要猜出谜底库中正确的单词。猜中的要求如下:请你写一个程序帮忙在谜底库中找到正确的谜底。谜面是多个单词,都需要找到对应的谜底,如果找不到的话,返回”not found”

算法大师! 3487

代码演示同类中调用@Transcation注解失效原因

Spring在扫描bean的时候,如果扫描到方法上有这些注解,那么spring会通过动态代理模式,为这个bean动态地生成一个代理类,在代理类中,会对有注解的这个方法,做一些增强处理,如给有@Transactional注解的方法开启transaction。当我们想要调用这个方法时,实际上是先调用了代理对象中被增强的方法,然后在代理对象中,又会调用我们实际的目标对象中的方法。在通过代理对象中转的这一过程中,像上边说的开启和提交transaction就实现了。

qq_45469225的博客 543

rk3568 点亮双LVDS 屏

承接文章《rk3568点亮LCD(lvds)》中仅仅只能使用亮单LVDS;经过厂商的努力,陆续发布新补丁。目前支持双lvds显示,缺憾是需要自己额外移植相关补丁。受限于通信频率和VOP编码能力,支持最大分辨仍然是1920x1080、60fps。

weixin_35723192的博客 3007

十七:反射与动态代理

跳转到总目录 文章目录01、Java反射机制概述1.1、使用反射,实现同上的操作1.2、反射的强大:调用类的私有结构02、理解Class类并获取Class实例2.3、Class类的理解2.4、获取Class实例的4种方式2.5、Class实例对应的结构的说明03、类的加载与ClassLoader的理解3.6、了解:类的加载过程3.7、了解:什么时候会发生类初始化?3.8、ClassLoader的理解3.9、使用ClassLoader加载配置文件04、通过反射,创建运行时类的对象4.1、举例体会反射的动态性0

本人主攻Java,希望自己能成为出色的程序员。 2万+

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

AOP在Spring中的应用(上)-- 与 AOP 动态代理有关的注解

EnableTransactionManagement,@EnableAspectJAutoProxy,@EnableAsync注解都有可能产生AOP动态代理@EnableTransactionManagement,@EnableAspectJAutoProxy注解注入的bpp,都是依靠AbstractAutoProxyCreator这个类完成动态代理的。如果它们同时存在,Spring中只会存在一个优先级更高的bpp。这两个注解指定的参数是互补的,对于特定需求,可以进行扩展。

好记性不如烂笔头 1495

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Retrofit中的注解反射与动态代理

title: JAVA基础|Retrofit中的注解反射与动态代理 date: 2024-03-07 13:48:21 categories: - Android开发 - Java知道 tags: - Intent通过自定义注解与反射实现页面跳转的参数注入: 代理模式类图

codeSong的博客 268

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Spring CGLIB 动态代理子类导致的注解丢失

在 Spring 中可以使用类级别的 @Validated 注解对整个类的方法做校验,实际运行时,Spring 会通过 CGLIB 生成基于类的代理,这个生成的代理是原始类的子类。 在 Spring 中可以使用类级别的@Validated 注解对整个类的方法做校验,实际运行时,Spring 会通过 CGLIB 生成基于类的代理,这个生成的代理是原始类的子类。而这个自动生成的子类不会继承原始类的注解,故在编写 Component 处理逻辑时检测不到原始类的注解。 问题再现 如下的一个类: @Validat.

编码行者的博客 2394

基于Spring AOP实现注解功能(示例、原理及无效情况说明)

1,正确示例 示例中通过注解增强被注解方法功能:数据保存到本地 db 时,同时将该数据封装成统一的消息格式发送到 kafka 1.1 定义注解 package com.demo; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Target(ElementType.METHOD)//...

ZBH的博客 785

基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别。

基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别。 我还是喜欢基于Schema风格的Spring事务管理,但也有很多人在用基于@Trasactional注解的事务管理,但在通过基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务是有区别的,我们接下来看看到底有哪些区别。       一、基础工作 首

jinnianshilongnian的专栏 3100

基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别...

一、基础工作 如下所示: 将xml声明式事务删除 <aop:config expose-proxy="true"> <!-- 只对业务逻辑层实施事务 --> <aop:pointcut id="txPointcut" expression="execution(* cn.javass..s...

aishai1059的博客 240

彻底搞懂Spring AOP

AOP(Aspect Oriented Programming)是一种面向切面的编程思想 Spring AOP 作为Spring最核心的能力之一,基于动态代理

Tan_xiong的博客 1037

Feign:原理、实践与优化

Feign 是一个声明式的 HTTP 客户端,简化了服务间的调用过程。

weixin_42564451的博客 716

十六:反射与动态代理

总目录 目录 01、Java反射机制概述 1.1、使用反射,实现同上的操作 1.2、反射的强大:调用类的私有结构 02、理解Class类并获取Class实例 2.3、Class类的理解 2.4、获取Class实例的4种方式 2.5、Class实例对应的结构的说明 03、类的加载与ClassLoader的理解 3.6、了解:类的加载过程 3.7、了解:什么时候会发生类初始化? 3.8、ClassLoader的理解 3.9、使用ClassLoader加载配置文件 04、通过...

黄烧牛肉面的博客 2336

8月2日SpringBoot学习笔记

通过通过execution函数来定义切点,注解为@Pointcut("execution()")被定义切点的类之后使用@Autoward注入时会注入此类的代理类(此类的子类,包含代理处理器,处理程序等等),而不是本类,通过动态代理实现。(本人太垃圾了真不懂所以直接看别人的吧)

tcwjy2021的博客 1192

2021-07-11基于动态代理的Spring事务管理

目录一、代理模式1.特点2.作用二、静态代理1.缺点2.代码示例三、动态代理(jdk)1.特点2.实现(1)InvocationHandler(2)Method(3)Proxy3.代码示例四、事务管理1.手动实现事务2.spring基于xml的声明式事务控制3.spring基于注解的声明式事务控制 一、代理模式 1.特点 (1)使用一个代理将对象包装起来, 然后用该代理对象取代原始对象。 (2)任何对原始对象的调用都要通过代理。 (3)代理对象决定是否以及何时将方法调用转到原始对象上。 2.作用 功能增强:

weixin_41465685的博客 536

day14-Junit、反射、注解、动态代理

3. 全部都设置暴力反射【设置访问权】【即使是private也可以访问】\2. 要用什么成员,就先获取对应的成员。\1. 先获取这个类的class对象。invoke(对象 ,参数…

uhb1223的博客 193
上一篇: 06_单元测试与反射
下一篇: CSS-2
code_stream
博客等级 码龄4年 1238粉丝 169原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值