在第一节中,我们自己模拟了一个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用户的日志记录工作

项目结构如下:

尚学堂Spring视频教程(五):Spring AOP的更多相关文章

  1. spring boot(五)Spring data jpa介绍

    在上篇文章springboot(二):web综合开发中简单介绍了一下spring data jpa的基础性使用,这篇文章将更加全面的介绍spring data jpa 常见用法以及注意事项 使用spr ...

  2. 框架应用:Spring framework (五) - Spring MVC技术

    软件开发中的MVC设计模式 软件开发的目标是减小耦合,让模块之前关系清晰. MVC模式在软件开发中经常和ORM模式一起应用,主要作用是将(数据抽象,数据实体传输和前台数据展示)分层,这样前台,后台,数 ...

  3. spring入门(五) spring mvc+hibernate

    核心是让SessionFactory由Spring管理 1.引入依赖 <!-- https://mvnrepository.com/artifact/org.springframework/sp ...

  4. Spring详解(五)------AOP

    这章我们接着讲 Spring 的核心概念---AOP,这也是 Spring 框架中最为核心的一个概念. PS:本篇博客源码下载链接:http://pan.baidu.com/s/1skZjg7r 密码 ...

  5. spring(五):AOP

    AOP(Aspect Oriented Programming) 面向切面编程,是一种编程范式,提供从另一个角度来考虑程序结构从而完善面向对象编程(OOP). 在进行OOP开发时,都是基于对组件(比如 ...

  6. 十五 Spring的AOP的注解的通知类型,切入点的注解

    Spring的注解的AOP的通知类型 @Before:前置通知 @AfterReturning:后置通知 @Around:环绕通知 @AfterThrowing:异常抛出通知 @After:最终通知 ...

  7. 【Spring Framework】Spring入门教程(五)AOP思想和动态代理

    本文主要讲解内容如下: Spring的核心之一 - AOP思想 (1) 代理模式- 动态代理 ① JDK的动态代理 (Java官方) ② CGLIB 第三方代理 AOP概述 什么是AOP(面向切面编程 ...

  8. [JAVA教程] 2016年最新spring4框架搭建视频教程 【尚学堂】

    Spring4框架 主讲:邹波 类型:SSH 适合对象:学习完javase.数据库技术.jdbc者 Spring4.0作为一个广泛使用的开源框架,它由Rod Johnson创建.它是为了解决企业应用开 ...

  9. Spring学习笔记4——AOP

    AOP 即 Aspect Oriented Program 面向切面编程 首先,在面向切面编程的思想里面,把功能分为核心业务功能,和周边功能. 所谓的核心业务,比如登陆,增加数据,删除数据都叫核心业务 ...

  10. Spring基础篇——Spring的AOP切面编程

    一  基本理解 AOP,面向切面编程,作为Spring的核心思想之一,度娘上有太多的教程啊.解释啊,但博主还是要自己按照自己的思路和理解再来阐释一下.原因很简单,别人的思想终究是别人的,自己的理解才是 ...

随机推荐

  1. Linux crontab命令格式与详情例子

    基本格式 : * * * * * command 分 时 日 月 周 命令 第1列表示分钟1-59 每分钟用*或者 */1表示 第2列表示小时1-23(0表示0点) 第3列表示日期1-31 第4列表示 ...

  2. JS的字符串处理

    1.字符串包含判断 var a = "qwer"; var b = "q"; if (a.contains(b)) { alert("1") ...

  3. Kali Linux additional tools setup

    The steps are pretty straight forward. The only tool that might cause some confusion is SMBexec. Thi ...

  4. FreeBSD 无线配置

    无线配置在 handbook 中早已有了,但 handbook 中采用写入配置文件的办法,缺乏灵活性,补充下 on the fly 的方法 假设网卡接口为 ath0 ifconfig wlan0 cr ...

  5. Baidu set to lose leading role in digital advertising _china daily

    advertising: n,广告 Online search giant Baidu Inc is set to loset its top spot in the nation's booming ...

  6. js 防止页面后退的方法

    //防止页面后退 history.pushState(null, null, document.URL); window.addEventListener('popstate', function ( ...

  7. HashMap 与 HashTable的区别

    1.HashTable的方法是同步的,HashMap未经同步,所以在多线程场合要手动同步HashMap这个区别就像Vector和ArrayList一样.可以用synchronized实现HashMap ...

  8. [API]使用Blueprint来高雅的编写接口文档 前后端api文档,移动端api文档

    网址:http://apiary.io/ 介绍:一款非常强大的前后端交互api设计编辑工具(编辑器采用Markdown类似的描述标记,非常高效),高颜值的api文档,还能生成多种语言的测试代码. 中文 ...

  9. 调试新技能get - powershell

    1. win+r -> powershell_ise 2. debug-process 3. type processname....WITHOUT ".exe"

  10. apache 使用 .htaccess 导致500错误

    今天在win主机上配置了一个apache+mysql+php 的环境,一切看似正常了.结果将程序转移过来,打开网站的时候,出现了500错误.于是乎查原因: 首先,怀疑的是连接mysql出错了,找出配置 ...