尚学堂Spring视频教程(五):Spring AOP-程序员宅基地

技术标签: java  测试  

  在第一节中,我们自己模拟了一个Spring,实现一个保存用户的操作,假如现在有一个需求,在保存的时候记录日志,该怎么做呢?  

  暂且将记录日志操作就简单的变为在保存用户前输出一句话“save start...”,不建议直接在UserDAOImpl的save方法里写代码,因为我们有时候可能得不到源码,这个时候可以添加一个UserDAOImpl2继承UserDAOImpl,然后调用父类的save方法

package com.bjsxt.dao.impl;

import com.bjsxt.model.User;

public class UserDAOImpl2 extends UserDAOImpl {
    @Override
    public void save(User user) {
        
        System.out.println("save start...");
        super.save(user);
        
    }
}
UserDAOImpl2

  注:配置文件被注入到UserService的bean的class要改为UserDAOImpl2,下面也一样

  看似实现了效果,但是这样很不灵活,因为只能继承一个类,而且父类发生变化,子类也必须跟着做出改变,我们可以再添加一个类继承UserDAOImpl,但是采用组合的方法

package com.bjsxt.dao.impl;

import com.bjsxt.aop.LogInterceptor;
import com.bjsxt.dao.UserDAO;
import com.bjsxt.model.User;

public class UserDAOImpl3 implements UserDAO {
    
    private UserDAO userDAO = new UserDAOImpl();
    
    public void save(User user) {
        System.out.println("save start...");
        /*new LogInterceptor().beforeMethod(null);*/
        userDAO.save(user);
        
        
    }

    /*public void delete() {
        // TODO Auto-generated method stub
        
    }*/
}
UserDAOImpl3

  问题又来了,如果系统有500个需要被注入的bean,每个bean都有一些操作需要被记录日志,难道要组合500个bean来实现这个功能吗?

  实际上可以给UserDAOImpl产生了一个代理,我们知道在代理模式中代理类除了可以调用目标对象的方法,也可以在方法前后加入自己的逻辑,在这里就是日志记录

  在JAVA基础知识:代理这篇文章中,介绍了Proxy类的静态方法newProxyInstance,这个方法需要三个参数,第一个是类装载器,第二个是目标对象的接口,第三个是InvocationHandler,这个最重要,定义了一个invoke方法,方法中可以调用目标对象的方法,也可以添加日志记录的逻辑代码

  新建一个包com.bjsxt.aop,添加类LogInterceptor继承InvocationHandler

package com.bjsxt.dao.impl;

import com.bjsxt.dao.UserDAO;
import com.bjsxt.model.User;


public class UserDAOImpl implements UserDAO {

    public void save(User user) {
        
        //Hibernate
        //JDBC
        //XML
        //NetWork
        System.out.println("user saved!");
    }

    public void delete() {
        System.out.println("user deteleted");
        
    }

}
UserDAOImpl
package com.bjsxt.aop;

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

public class LogInterceptor implements InvocationHandler {
    private Object target;
    
    public Object getTarget() {
        return target;
    }

    public void setTarget(Object target) {
        this.target = target;
    }

    public void beforeMethod(Method m) {
        
        System.out.println(m.getName() + " start");
    }

    public Object invoke(Object proxy, Method m, Object[] args)
            throws Throwable {
        beforeMethod(m);
        m.invoke(target, args);
        return null;
    }
}
InvocationHandler接口的实现类
    @Test
    public void testProxy() {
        UserDAO userDAO = new UserDAOImpl();
        LogInterceptor li = new LogInterceptor();
        li.setTarget(userDAO);
        UserDAO userDAOProxy = (UserDAO)Proxy.newProxyInstance(userDAO.getClass().getClassLoader(), userDAO.getClass().getInterfaces(), li);
        System.out.println(userDAOProxy.getClass());
        userDAOProxy.delete();
        userDAOProxy.save(new User());
        
    }
单元测试

  我们只需要写一次日志记录的代码,就完成delete和add用户的日志记录工作

  项目结构如下:

转载于:https://www.cnblogs.com/SamFlynn/p/4604148.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_30845171/article/details/96888737

智能推荐

WINCE 6.0 5.0 区别_win ce5.0 ce6.0区别-程序员宅基地

文章浏览阅读2.6k次。CE 6.0 R2对CE 6.0的功能增加:1 Core OS2 IE3 Media Player4 RDP 对于从事廋客房端开发的人员有很大的帮助5 VoIP6 Web Services一) CE OS的改变,只有两次1 2.0->3.02 5.0->6.0但是4.2到5.0驱动变化较大,导致从4.2到5.0的移植需要很长的时间二) CE 6.0与5.0的主要区别1 CE6.0的Ker_win ce5.0 ce6.0区别

图像meta信息中XMP[drone-dji]如何获取_xmp.drone-dji.lrftargetdistance-程序员宅基地

文章浏览阅读1.4k次。在处理大疆无人机拍的图像时,官方给的图像处理指南里出现了这么一句:于是去网上查找如何读取图像meta信息,找到了许多花里胡哨的方法,比如python代码、java代码、网站代查之类,最终我发现,最简便的方法就是:用写字板的方式打开图像,然后查找”xmp“ ,需要的参数就全能找到了。唯一的不足就是这个方法的效率太低了,写字板打开tif文件奇慢无比。..._xmp.drone-dji.lrftargetdistance

云服务器(阿里云)安装kafka及相关报错处理(WARN Connection request from old client /58.247.201.56:31365; will be dropp)-程序员宅基地

文章浏览阅读4.2k次。云服务器安装kafka,部署zookeeper时有如下注意点:1、在云服务器安全组中开放:2181、9092端口2、zookeeper.connect改成公网IP3、listeners=PLAINTEXT:// 必须填内网IPlisteners=PLAINTEXT://**.**.**.**:90924、配置外部代理地址必须填公网IPadvertised.listeners=PLAINTEXT://**.**.**.**:9092advertised.host.name=*.._connection request from old client

【连接池】-从源码到适配(上),你遇到过数据库连接池的问题吗?This connection has been closed_failed to initialize pool: this connection has bee-程序员宅基地

文章浏览阅读1.2k次,点赞19次,收藏22次。本文从项目需求出发到项目最终发版提测,讲述一下项目中遇到的问题(MyBatis数据库厂商适配、查看数据库链接、连接池失效等)以及打怪升级过程(思路),文章中会提到涉及到的坑以及解决办法。相信看完,多少会给你提供一些价值。_failed to initialize pool: this connection has been closed.

android listpreference 自定义,自定义android preference组件-程序员宅基地

文章浏览阅读179次。e() {return mDisableDependentsState;}public void setDisableDependentsState(boolean disableDependentsState) {mDisableDependentsState = disableDependentsState;}@Overrideprotected Object onGetDefaultValu..._android 自定义listpreference

射频MOS管和三极管优缺点对比_mos管比起三极管有什么优势-程序员宅基地

文章浏览阅读5.1k次。MOS管优点:1.具有良好的温度特性。2.具有良好的噪声特性。3.输入阻抗高。4.MOS管的漏极电流具有二次函数特性,三极管的集电极电流是指数形式。5.MOS管的上限频率远远超过三极管的上限工作频率。6.MOS管功耗较小。MOS管缺点:1.增益通常较低。2.输入阻抗高,导致匹配网络难设计。3.相对于三极管,MOS管的功率容量偏低..._mos管比起三极管有什么优势

随便推点

【TCP/IP】 以太网流量控制------pause流控_流控 pause 发送时机 计算-程序员宅基地

文章浏览阅读7.4k次,点赞10次,收藏94次。文章目录一、以太网的流量控制二、pause流控的原理和实现1.pause流控原理2.pause消息格式3.pause流控处理逻辑4.pause流控芯片上的实现三、pause流控的作用与副作用1.pause流控的作用2.pause流控的副作用四、pause流控对性能的影响分析1.性能影响2.风险评估最近定位了一个pause流控引发的产品问题,对pause流控进行了详细的研究,由于网上关于pause流控的相关资料非常少,这里将所有pause流控相关的知识总结整理一下,供大家参考。一、以太网的流量控制以_流控 pause 发送时机 计算

对linux下各种profiling工具的心得_profiling的工作-程序员宅基地

文章浏览阅读4k次。第一次写博_profiling的工作

tf.nn.dropout() 警报信息处理_please use `rate` instead of `keep_prob`. rate sho-程序员宅基地

文章浏览阅读8.2k次,点赞11次,收藏23次。WARNING: Logging before flag parsing goes to stderr.calling dropout (from tensorflow.python.ops.nn_ops) with keep_prob is deprecated and will be removed in a future version.Instructions for updatin..._please use `rate` instead of `keep_prob`. rate should be set to `rate = 1 -

vmware12 的kernel module updater解决方法_vmware kernel module update-程序员宅基地

文章浏览阅读6.9k次。vmware12 的kernel module updater解决方法_vmware kernel module update

Typescript 开发工具Vscode自动编译.ts文件_tsconfig中导入 d.ts-程序员宅基地

文章浏览阅读350次。1.创建tsconfig.json文件tsc–init 生成配置文件首先你需要进入你的项目目录cmd然后输入tsc --init这样的话该目录下就会生成一个tsconfig.json的文件下一步你需要把tsconfig.json文件的outDir 改一下下一步去创建一个ts 文件最后去终端运行一下就会生成js文件了..._tsconfig中导入 d.ts

用Visual Studio建立第一个ASP.NET页面_vs2022怎么创建aspx文件-程序员宅基地

文章浏览阅读2.6w次,点赞17次,收藏84次。1.新建一个项目 (1)直接在VS开始界面上选择“新建项目 (2)在菜单上选择“文件”、“新建”、“项目”2.在弹出的窗口中选择“Visual C#”--->“Web”---->"ASP.NET空Web应用程序",注意选择的是.NET Framework4框架,然后输入你所想输入的项目名称,点击“确定”,就成功新建了一个ASP.NET项目_vs2022怎么创建aspx文件