动态代理的两个使用方式(手动实现+SpringAOP实现)-Demo

这篇具有很好参考价值的文章主要介绍了动态代理的两个使用方式(手动实现+SpringAOP实现)-Demo。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、手动实现

1、具体代码

package com.xch.proxy;

/**
 * 具体业务接口
 *
 * @author XuChenghe
 * @date 2023/8/18 15:09
 */
public interface Star {
    
    /**
     * 唱歌方法
     *
     * @param name
     * @return
     */
    String sing(String name);
    
    /**
     * 跳舞方法
     */
    void dance();
    
}
package com.xch.proxy;

/**
 * 具体业务实现类
 *
 * @author XuChenghe
 * @date 2023/8/18 15:06
 */
public class BigStar implements Star {
    private String userName;
    
    public BigStar(String userName) {
        this.userName = userName;
    }
    
    /**
     * {@inheritDoc}
     */
    public String sing(String songName) {
        System.out.println(this.userName + "正在唱:" + songName);
        return "谢谢!谢谢!";
    }
    
    /**
     * {@inheritDoc}
     */
    public void dance() {
        System.out.println(this.userName + "正在优美的跳舞~~");
    }
    
}
package com.xch.proxy;

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

/**
 * 动态代理的工具类(产生代理的)
 * -手动实现原生动态代理
 *
 * @author XuChenghe
 * @date 2023/8/18 15:11
 */
public class ProxyUtil {
    
    public static Star createProxy(BigStar bigStar) {
        // 参数1:ClassLoader用于指定一个类加载器
        // 参数2:指定生成的代理有哪些方法
        // 参数3:用来指定生成的代理对象要干什么事情(动态代理的核心)
        Star starProxy = (Star) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(),
                new Class[]{Star.class}, new InvocationHandler() {
                    // 回调方法
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // 动态代理要做的事情,会在这里写代码
                        if ("sing".equals(method.getName())) {
                            System.out.println("准备话筒,收钱20万");
                        } else if ("dance".equals(method.getName())) {
                            System.out.println("准备场地,收钱100万");
                        }
                        return method.invoke(bigStar, args);
                    }
                }
        );
        return starProxy;
    }
    
}
package com.xch.proxy;

/**
 * 运行启动测试类
 *
 * @author XuChenghe
 * @date 2023/8/18 15:21
 */
public class LaunchTest {
    
    public static void main(String[] args) {
        Star starProxy = ProxyUtil.createProxy(new BigStar("杨超越"));
        
        String result = starProxy.sing("好日子");
        System.out.println(result);
        
        starProxy.dance();
    }
    
}

二、SpringAOP实现

1、pom文件依赖

<!-- Spring的AOP切面编程启动环境依赖组 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- Spring的事务依赖 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
</dependency>

2、具体代码文章来源地址https://www.toymoban.com/news/detail-662914.html

package com.xch.proxy_product;

/**
 * 具体业务接口
 *
 * @author XuChenghe
 * @date 2023/8/18 15:09
 */
public interface Star {
    
    /**
     * 实际生产中使用的代理调用
     *
     * @param name
     * @return
     */
    String proxySing(String name);
    
    /**
     * 实际生产中使用的代理调用
     */
    void proxyDance();
    
}
package com.xch.proxy_product;

import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 具体业务实现类
 *
 * @author XuChenghe
 * @date 2023/8/18 15:06
 */
@Service
public class BigStar implements Star {
    
    /**
     * 唱歌方法
     *
     * @param songName
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public String sing(String songName) {
        System.out.println("杨超越正在唱:" + songName);
        return "谢谢!谢谢!";
    }
    
    /**
     * 跳舞方法
     */
    @Transactional(rollbackFor = Exception.class)
    public void dance() {
        System.out.println("杨超越正在优美的跳舞~~");
    }
    
    /**
     * {@inheritDoc}
     */
    @Transactional(rollbackFor = Exception.class)
    public String proxySing(String songName) {
        System.out.println("准备话筒,收钱20万");
        return getCurrentProxy().sing("好日子");
    }
    
    /**
     * {@inheritDoc}
     */
    @Transactional(rollbackFor = Exception.class)
    public void proxyDance() {
        System.out.println("准备场地,收钱100万");
        getCurrentProxy().dance();
    }
    
    /**
     * 获取当前类的代理
     *
     * @return 当前类的代理
     */
    private static BigStar getCurrentProxy() {
        return (BigStar) AopContext.currentProxy();
    }
    
}
package com.xch.proxy_product;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/**
 * 通用业务的切面类
 *
 * @author XuChenghe
 * @date 2023/8/20 8:55
 */
@Aspect // 声明该类的作用:切面类
@Component // 等价于@Configuration:交由Spring的IOC容器管理
public class BigStarAspect {
    
    /**
     * 定义公共切入点
     * -假设proxy_product是service业务层包
     * -则通过以下表达式匹配该业务包下的所有子孙类的所有public修饰的方法
     *
     * 另外,配置的切入表达式必须是符合public修饰的方法
     * 因为,Spring事务即AOP的底层通过动态代理生成代理调用该方法时,
     * 会判断方法只能是public修饰的Modifier.isPublic(method.getModifiers())
     */
    @Pointcut("execution(public * com.xch.proxy_product..*(..))")
    public void myPointcut() {
        // 公共切入点
    }
    
    /**
     * 配置切面方法(环绕通知):方法增强
     *
     * @param pjp 连接点:当前切入方法的信息
     * @return 方法执行的返回结果
     * @throws Throwable 方法执行时抛出的异常
     */
    @Around("myPointcut()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("=====环绕通知(开始)=====");
        // 前置增强代码
        Object proceed = pjp.proceed();
        // 后置/返回增强代码
        // 最终增强代码
        // 抛出异常后增强代码
        System.out.println("=====环绕通知(结束)=====");
        return proceed;
    }
}
package com.xch;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

/**
 * 启用Spring的动态代理,默认使用JDK动态代理(由proxyTargetClass控制)
 */
@SpringBootApplication
@EnableAspectJAutoProxy(exposeProxy = true)
public class SubDynamicProxyApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(SubDynamicProxyApplication.class, args);
    }
    
}
package com.xch.proxy_product;

import org.junit.jupiter.api.Test;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

/**
 * 运行启动测试类
 *
 * @author XuChenghe
 * @date 2023/8/18 15:21
 */
@SpringBootTest
public class LaunchTest {
    
    @Autowired
    private Star star;
    
    @Test
    public void launch() {
        String result = star.proxySing("好日子");
        System.out.println(result);
    
        System.out.println();
        star.proxyDance();
    
        // 判断该注入类是否代理类
        // -Spring的IOC容器中默认都是原生对象
        // -只有配置了AOP增强的对象才是代理对象
        System.out.println(AopUtils.isAopProxy(star));
    }
    
}

到了这里,关于动态代理的两个使用方式(手动实现+SpringAOP实现)-Demo的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【kafka】Java客户端代码demo:自动异步提交、手动同步提交及提交颗粒度、动态负载均衡

    kafka版本为3.6,部署在3台linux上。 maven依赖如下: 生产者、消费者和topic代码如下: 这里先简单解释一下, kafka的topic只是一个逻辑上的概念,实际上的物理存储是依赖分布在broker中的分区partition来完成的 。kafka依赖的zk中有一个 __consumer_offsets [1]话题,存储了所有consumer和g

    2024年01月19日
    浏览(41)
  • Redis手动实现分布式锁-Demo

    1、pom文件依赖  2、具体实现

    2024年02月11日
    浏览(25)
  • IDEA 手动设置HTTP代理(使用代理解决Translation 翻译失败)

    大家好,我是垃圾佬,一个正在学Java的 “无业游民 ” 最近谷歌翻译以使用率太低为由退出大陆地区,那么在IDEA经常使用一个插件 Translation 使用谷歌翻译引擎必然是不能用了,但是翻译的接口还在,所以也有对应的解决方法,修改电脑本身的 host 文件重新指向可以 ping 通

    2024年01月16日
    浏览(33)
  • 在 Docker 容器中使用代理,你需要手动在容器中设置代理

    Docker 容器里的进程默认情况下不会共享宿主机的代理配置,因为 Docker 容器是独立的运行环境,它有自己的网络栈和 IP 地址。容器中的进程和宿主机上的进程是相互隔离的。 如果你需要在 Docker 容器中使用代理,你需要手动在容器中设置代理。有几种方法可以做到: 使用

    2024年02月14日
    浏览(46)
  • Nginx(一)介绍Nginx、正向代理和实现反向代理的两个实例

    中国Nginx官网:https://www.nginx-cn.net/ GitHub地址:https://github.com/nginxinc/ 客户端想访问tomcat服务器,只需要访问ww.baidu.com。对真实的服务器IP是隐藏的 1、反向代理实例一(反向代理,访问www.123.com) 步骤一:修改主机映射“C:WindowsSystem32driversetchosts” 步骤二:修改Nginx中的配

    2024年02月08日
    浏览(38)
  • MyBatis的代理开发方式、动态sql语句和typeHandlers和plugins标签实战

    接上篇博客: MyBatis基础知识和快速入门、MyBatis核心配置文件讲解,本文继续讲解MyBatis动态SQL语句、typeHandlers和plugins标签。 传统开发方式 编写UserDao接口 编写UserDaoImpl实现 mapper文件 测试传统方式 代理开发方式 代理开发方式介绍 采用 Mybatis 的代理开发方式实现 DAO 层的开发

    2023年04月27日
    浏览(31)
  • cglib动态代理、jdk动态代理及spring动态代理使用

    NickelBeforeAdvice.java方法执行之前 NickelAfterReturningAdvice.java方法执行之后 NickelAroundadvice.java环绕方法 NickelThrowAdvice.java抛异常方法 UserService.java抛异常方法 SpringProxtFactoryTest.java测试方法 NickelStaticMethodMatherPointcut.java方法匹配的方法 NickelPointcutAdvisor.java切面方法 SpringProxtFactoryTest.j

    2024年02月15日
    浏览(37)
  • Linux 安装maven两种方式(使用yum或手动安装)

    yum install maven -y 配置阿里云镜像 ​vim /etc/maven/settings.xml​​ ,mirrors节点下添加: 下载maven wget https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz   解压 tar -zvxf apache-maven-3.6.3-bin.tar.gz   移动目录 mv apache-maven-3.6.3 /usr/local/maven 添加环境变量  vi /etc/profile  

    2024年02月08日
    浏览(38)
  • 【数据结构】栈和队列的模拟实现(两个方式实现)

    💓作者简介: 加油,旭杏,目前大二,正在学习 C++ , 数据结构 等👀 💓作者主页:加油,旭杏的主页👀 ⏩本文收录在:再识C进阶的专栏👀 🚚代码仓库:旭日东升 1👀 🌹欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖        这一篇博客将学习栈和队列的相关知识, 栈

    2024年02月05日
    浏览(30)
  • Spring5系列学习文章分享---第三篇(AOP概念+原理+动态代理+术语+Aspect+操作案例(注解与配置方式))

    开篇: 欢迎再次来到 Spring 5 学习系列!在这个博客中,我们将深入研究 Spring 框架的AOP概念+原理+动态代理+术语+Aspect+操作案例(注解与配置方式)。 概念 什么是AOP (1)面向切面编程(方面),利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得 业务逻辑各部分之间的

    2024年01月24日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包