Spring之aop

什么是AOP:
Aspect Oriented Programming(AOP)是较为热门的一个话题。AOP,国内大致译作“面向切面编程”。

“面向切面编程”,这样的名字并不是非常容易理解,且容易产生一些误导。
笔者不止一次听到类似“OOP/OOD11即将落伍,AOP是新一代软件开发方式”这样的发言。而在AOP中,Aspect的含义,可能更多的理解为“切面”比较合适。所以笔者更倾向于“面向切面编程”的译法。可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。
AOP实际是GoF设计模式的延续,设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,提高代码的灵活性和可扩展性,AOP可以说也是这种目标的一种实现。 
应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。
AOP主要功能
日志记录,性能统计,安全控制,事务处理,异常处理等等wn及扩展

AOP中关键性概念 :

连接点(Joinpoint):程序执行过程中明确的点,如方法的调用,或者异常的抛出.
目标(Target):被通知(被代理)的对象

通知(Advice):在某个特定的连接点上执行的动作,同时Advice也是程序代码的具体实现,例如一个实现日志记录的代码(通知有些书上也称为处理)

代理(Proxy):将通知应用到目标对象后创建的对象(代理=目标+通知),请注意:只有代理对象才有AOP功能,而AOP的代码是写在通知的方法里面的

切入点(Pointcut):多个连接点的集合,定义了通知应该应用到那些连接点。(也将Pointcut理解成一个条件 ,此条件决定了容器在什么情况下将通知和目标组合成代理返回给外部程序)

适配器(Advisor):适配器=通知(Advice)+切入点(Pointcut)

定义一个接口,有购书和评论两个方法 IBookBiz:

package com.liuwenwu.aop.biz;

public interface IBookBiz {
    // 购书
    public boolean buy(String userName, String bookName, Double price);

    // 发表书评
    public void comment(String userName, String comments);
}

BookBizImpl 实现接口

package com.liuwenwu.aop.biz.impl;

import com.liuwenwu.aop.biz.IBookBiz;
import com.liuwenwu.aop.exception.PriceException;
/**
 * 目标
 * @author ASUS
 *
 */
public class BookBizImpl implements IBookBiz {

    public BookBizImpl() {
        super();
    }

    public boolean buy(String userName, String bookName, Double price) {
        // 通过控制台的输出方式模拟购书
        if (null == price || price <= 0) {
            throw new PriceException("book price exception");
        }
        System.out.println(userName + " buy " + bookName + ", spend " + price);
        return true;
    }

    public void comment(String userName, String comments) {
        // 通过控制台的输出方式模拟发表书评
        System.out.println(userName + " say:" + comments);
    }

}

异常处理 PriceException:

package com.liuwenwu.aop.exception;

public class PriceException extends RuntimeException {

    public PriceException() {
        super();
    }

    public PriceException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }

    public PriceException(String message, Throwable cause) {
        super(message, cause);
    }

    public PriceException(String message) {
        super(message);
    }

    public PriceException(Throwable cause) {
        super(cause);
    }
    
}

1、前置通知 MyMethodBeforeAdvice:

package com.liuwenwu.aop.advise;

import java.lang.reflect.Method;
import java.util.Arrays;

import org.springframework.aop.MethodBeforeAdvice;

/**
 * 前置通知
 * 买书、评论前加系统日志   
 * @author ASUS
 *
 */
public class MyMethodBeforeAdvice implements MethodBeforeAdvice {

    @Override
    public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
//        哪个类被调用了
        String clzName=arg2.getClass().getName();
//        哪个方法被调了
        String methodNname=arg0.getName();
//        参数
        String params=Arrays.toString(arg1);
        System.out.println("【系统日志】:"+clzName+"."+methodNname+"("+params+")");    
    }
}

测试类 Demo1:

package com.liuwenwu.aop.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.liuwenwu.aop.biz.IBookBiz;

public class Demo1 {

    public static void main(String[] args) {
//        从spring中获取上下文
        ApplicationContext context=new ClassPathXmlApplicationContext("/spring-context.xml");
//        IBookBiz bean = (IBookBiz) context.getBean("bookbiz");
//        System.out.println(bean.getClass());
        //代理对象
        IBookBiz bean = (IBookBiz) context.getBean("bookbizproxy");
//        System.out.println(bean.getClass());
        
//        报错之后,程序终止
        bean.buy("三毛", "三毛流浪记", 55d);
        bean.comment("三毛", "真的只有三毛");
    }
}

前置通知会在方法执行前就运行

【系统日志】:com.liuwenwu.aop.biz.impl.BookBizImpl.buy([三毛, 三毛流浪记, 55.0])
三毛 buy 三毛流浪记, spend 55.0
【系统日志】:com.liuwenwu.aop.biz.impl.BookBizImpl.comment([三毛, 真的只有三毛])
三毛 say:真的只有三毛

2、后置通知 MyAfterReturningAdvice

package com.liuwenwu.aop.advise;

import java.lang.reflect.Method;
import java.util.Arrays;

import org.springframework.aop.AfterReturningAdvice;

/**
 * 后置通知
 * 买书返利
 * @author ASUS
 *
 */
public class MyAfterReturningAdvice implements AfterReturningAdvice {

    @Override
    public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
        String clzName=arg3.getClass().getName();
        String methodNname=arg1.getName();
        String params=Arrays.toString(arg2);
        System.out.println("【后置通知(买书返利)】:"+clzName+"."+methodNname+"("+params+")");
    }
}

后置通知在方法执行后会运行

【系统日志】:com.liuwenwu.aop.biz.impl.BookBizImpl.buy([三毛, 三毛流浪记, 55.0])
三毛 buy 三毛流浪记, spend 55.0
【后置通知(买书返利)】:com.liuwenwu.aop.biz.impl.BookBizImpl.buy([三毛, 三毛流浪记, 55.0])
【系统日志】:com.liuwenwu.aop.biz.impl.BookBizImpl.comment([三毛, 真的只有三毛])
三毛 say:真的只有三毛
【后置通知(买书返利)】:com.liuwenwu.aop.biz.impl.BookBizImpl.comment([三毛, 真的只有三毛])

3、环绕通知=前置通知+后置购置  MyMethodInterceptor:

package com.liuwenwu.aop.advise;

import java.util.Arrays;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

/**
 * 环绕通知
 * 类似拦截器,会包括切入点,目标类前后都会执行代码。
 * @author ASUS
 *
 */
public class MyMethodInterceptor implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation arg0) throws Throwable {
        String clzName=arg0.getThis().getClass().getName();
        String methodNname=arg0.getMethod().getName();
        String params=Arrays.toString(arg0.getArguments());
        System.out.println("【环绕通知(前后都有)】:"+clzName+"."+methodNname+"("+params+")");
//        returnValue是代理对象调用目标方法的返回值
        Object returnValue=arg0.proceed();
        System.out.println("【环绕通知(前后都有)】:"+clzName+"."+methodNname+"("+params+")"+"方法调用的返回值:"+returnValue);
        return returnValue;
    }

}

环绕通知在方法执行前后都会运行

【系统日志】:com.liuwenwu.aop.biz.impl.BookBizImpl.comment([三毛, 真的只有三毛])
【环绕通知(前后都有)】:com.liuwenwu.aop.biz.impl.BookBizImpl.comment([三毛, 真的只有三毛])
三毛 say:真的只有三毛
【环绕通知(前后都有)】:com.liuwenwu.aop.biz.impl.BookBizImpl.comment([三毛, 真的只有三毛])方法调用的返回值:null
【后置通知(买书返利)】:com.liuwenwu.aop.biz.impl.BookBizImpl.comment([三毛, 真的只有三毛])

  4、异常通知 

package com.liuwenwu.aop.advise;

import org.springframework.aop.ThrowsAdvice;

import com.liuwenwu.aop.exception.PriceException;
/**
 * 异常通知
 * @author ASUS
 *
 */
public class MyThrowsAdvice implements ThrowsAdvice {
    public void afterThrowing( PriceException ex ) {
        System.out.println("价格输入有误,购买失败,请重新输入!!!");
        
    }
}

异常通知的作用是在程序出了BUG终止是也会先运行完异常通知里的代码

信息: Loading XML bean definitions from class path resource [spring-context.xml]
Exception in thread "main" 【系统日志】:com.liuwenwu.aop.biz.impl.BookBizImpl.buy([三毛, 三毛流浪记, -55.0])
价格输入有误,购买失败,请重新输入!!!
com.liuwenwu.aop.exception.PriceException: book price exception

spring-context.xml配置

<!-- aop知识点 -->
    <!-- 目标 -->
    <bean id="bookbiz" class="com.liuwenwu.aop.biz.impl.BookBizImpl"></bean>
    
    <!-- 前置通知 -->
    <bean id="myMethodBeforeAdvice" class="com.liuwenwu.aop.advise.MyMethodBeforeAdvice"></bean>
    
    <!-- 后置通知 -->
    <bean id="myAfterReturningAdvice" class="com.liuwenwu.aop.advise.MyAfterReturningAdvice"></bean>
    
    <!-- 环绕通知 -->
    <bean id="myMethodInterceptor" class="com.liuwenwu.aop.advise.MyMethodInterceptor"></bean>
    
    <!-- 异常通知 -->
    <bean id="myThrowsAdvice" class="com.liuwenwu.aop.advise.MyThrowsAdvice"></bean>
    
    <!-- 过滤通知 -->
    <bean id="myAfterReturningAdvicePlus" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <!-- 过滤规则 -->
        <property name="advice" ref="myAfterReturningAdvice"></property>
        <!-- <property name="pattern" value=".*buy"></property> -->
        <property name="patterns">
            <list>
                <value>.*buy</value>
            </list>
        </property>
    </bean>
    
    <!-- 目标+通知=代理对象 -->
    <bean id="bookbizproxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!-- 目标 -->
        <property name="target" ref="bookbiz"></property>
        <!-- 代理的接口(目标对象所实现的接口) -->
        <property name="proxyInterfaces">
            <list>
                <value>com.liuwenwu.aop.biz.IBookBiz</value>
            </list>
        </property>
        <!-- 通知 -->
        <property name="interceptorNames">
            <list>
                <value>myMethodBeforeAdvice</value>
                <value>myAfterReturningAdvice</value>
                <!-- <value>myAfterReturningAdvicePlus</value> -->
                <!-- <value>myMethodInterceptor</value> -->
                <value>myThrowsAdvice</value>
            </list>
        </property>
    </bean>

5、过滤通知:

<bean id="myAfterReturningAdvicePlus" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <!-- 过滤规则 -->
        <property name="advice" ref="myAfterReturningAdvice"></property>
        <!-- <property name="pattern" value=".*buy"></property> -->
        <property name="patterns">
            <list>
                <value>.*buy</value>
            </list>
        </property>
    </bean>

结果:评论后没有返利

【系统日志】:com.liuwenwu.aop.biz.impl.BookBizImpl.buy([三毛, 三毛流浪记, 55.0])
三毛 buy 三毛流浪记, spend 55.0
【后置通知(买书返利)】:com.liuwenwu.aop.biz.impl.BookBizImpl.buy([三毛, 三毛流浪记, 55.0])
【系统日志】:com.liuwenwu.aop.biz.impl.BookBizImpl.comment([三毛, 真的只有三毛])
三毛 say:真的只有三毛

 

转载于:https://www.cnblogs.com/xiatian3452/p/11371656.html

本项目是一个基于SSM(Spring+SpringMVC+MyBatis)后端框架与Vue.js前端框架开发的疫情居家办公系统。该系统旨在为居家办公的员工提供一个高效、便捷的工作环境,同时帮助企业更好地管理远程工作流程。项目包含了完整的数据库设计、前后端代码实现以及详细的文档说明,非常适合计算机相关专业的毕设学生和需要进行项目实战练习的Java学习者。 系统的核心功能包括用户管理、任务分配、进度跟踪、文件共享和在线沟通等。用户管理模块允许管理员创建和管理用户账户,分配不同的权限。任务分配模块使项目经理能够轻松地分配任务给团队成员,并设置截止日期。进度跟踪模块允许员工实时更新他们的工作状态,确保项目按计划进行。文件共享模块提供了一个安全的平台,让团队成员可以共享和协作处理文档。在线沟通模块则支持即时消息和视频会议,以增强团队之间的沟通效率。 技术栈方面,后端采用了Spring框架来管理业务逻辑,SpringMVC用于构建Web应用程序,MyBatis作为ORM框架简化数据库操作。前端则使用Vue.js来实现动态用户界面,搭配Vue Router进行页面导航,以及Vuex进行状态管理。数据库选用MySQL,确保数据的安全性和可靠性。 该项目不仅提供了一个完整的技术实现示例,还为开发者留下了扩展和改进的空间,可以根据实际需求添加新功能或优化现有功能。
本项目是一个基于SSM(Spring+SpringMVC+MyBatis)后端框架与Vue.js前端框架开发的网上球鞋竞拍系统。该项目旨在为球鞋爱好者提供一个便捷、高效的在线竞拍平台,用户可以在此平台上浏览、搜索、竞拍心仪的球鞋,并参与到各种有趣的竞拍活动中。 系统的主要功能包括用户注册登录、球鞋信息展示、竞拍活动创建与管理、实时竞拍以及交易安全保障等。用户可以通过注册账号后,浏览平台上发布的各类球鞋信息,包括品牌、型号、颜色、尺码以及当前竞拍状态等。系统支持用户创建和管理自己的竞拍活动,设定竞拍规则和时间,同时提供实时竞拍功能,确保公平、透明的交易过程。 在技术实现上,后端采用SSM框架进行开发,Spring负责业务逻辑层,SpringMVC处理Web请求,MyBatis进行数据库操作,保证了系统的稳定性和扩展性。前端则使用Vue.js框架,结合Axios进行数据请求,实现了前后端分离,提高了开发效率和用户体验。 数据库设计方面,系统采用了MySQL数据库,存储用户信息、球鞋信息、竞拍活动等数据,确保数据的安全性和完整性。此外,项目还包含了详细的文档资料,包括需求分析、系统设计、数据库设计以及测试报告等,为项目的实施和维护提供了有力的支持。 该项目不仅适合作为计算机相关专业学生的毕业设计题目,也适合Java学习者进行实战练习,通过在此基础上进行功能扩展和改进,可以进一步提升编程技能和项目管理能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值