SpringAOP —— 代理模式(记录使用方法)

编程入门 行业动态 更新时间:2024-10-19 14:43:48

SpringAOP —— 代理模式(记录<a href=https://www.elefans.com/category/jswz/34/1769874.html style=使用方法)"/>

SpringAOP —— 代理模式(记录使用方法)

前段时间在公司内网看到一篇关于AOP的文章,今天记录学习一下。

目录

什么是springAOP:

springAop原理:

静态代理:

动态代理: 

SpringAOP上手使用:

SpringAOP的优势和缺点:

SpringAOP总结:


什么是springAOP:

        首先介绍什么是springAop。官方介绍是面向切面编程,首先这是一种编程思想,基于java面向对象编程(OOP)的一种补充。面向对象变成思想是指万物皆对象。处理对象的过程叫方法,面向切面编程就是把方法看成一个整体,在不改变原有方法原有代码的情况下改变方法执行过程。

springAop原理:

        这种神奇的效果是怎么实现的呢?这个要归功于23种设计模式的代理模式,要理解面向切面编程,必须要先理解代理模式。
        代理模式理解很简单,比如你是彭于晏,但是你只专注于表演这个能力,只能拿到表演的钱,现在你特别出名,好多公司找你做代言,但你没空去洽谈,这个时候你就需要一个经纪人,经纪人会帮你接代言,帮你管理粉丝,帮你接戏,这样你的工作没有变,但是收入增加了。
        这个过程中,彭于晏代表是原生对象。而全权代表彭于晏的经纪人被称为代理对象。当我需要彭于晏表演的时候,我去找经纪人,这个过程叫代理模式。

代理模式的两种常见的实现方式:静态代理,动态代理

静态代理:

先说静态代理:静态代理优点是:好理解、好观察;缺点是:难维护、死板、不适合在动态的项目需求中使用。

/*** 功能接口*/
public interface Function {// 人物技能public void sill();}
/*** 演员类*/
public class Actor implements Function {@Overridepublic void sill() {System.out.println("我是彭于晏,我会表演!");}}
public class Agent implements Function {private Function obj;public Agent(Function obj){this.obj = obj;}@Overridepublic void sill() {System.out.println("我是经纪人,我会接代言,管粉丝!(注:动态代理实现)");obj.sill();}
}
public static void main(String[] args) {// 静态代理测试Agent agent = new Agent(new Actor());agent.sill();}

 

         这就是静态代理,目标对象和代理对象都需要实现自己的父类方法,一旦父类修改或新增了方法,需要在所有子类中一起变动,维护十分困难,所以一般在项目中很少使用静态代理。

动态代理: 

再说动态代理:动态代理优点是:好使用、好维护;缺点是:不好理解、不好观测;
接口部分不变,演员(彭于晏)部分不变:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*** 动态代理实现*/
public class AgentProxy {private Object object;public AgentProxy(Object object) {this.object = object;}// 利用反射给目标对象生成代理对象public Object getProxyInstance() {return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("我是经纪人,我会接代言,管粉丝!(注:动态代理实现)");// 执行目标对象方法Object invoke = method.invoke(object, args);return invoke;}});}}
 public static void main(String[] args) {// 动态代理测试Function fun = new Actor();AgentProxy agentProxy = new AgentProxy(new Actor());Function proxyInstance = (Function) agentProxy.getProxyInstance();proxyInstance.sill();}

 

 所谓动态代理就是借用反射来创建代理对象,借用反射的特性来创建代理对象的好处就是通用性极高,这样就避免了上层接口改变,代理对象也要修改。

SpringAOP上手使用:

        现在明白springAOP是干啥的,接下来展示springAOP在实际项目中的使用,SpringAOP已经实现了自动创建动态代理,我们只需要学会正确调用即可。

一、引入AOP依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>注:加入新依赖后要更新依赖。

二、使用切面注解@Aspect

import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;@Component
@Aspect    // 定义一个切面
public class AgentProxy {}

 切面:定义当前类是切面类,需要给每一个满足切面条件的类生成不同的代理对象。

三、定义需要的通知

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;@Component
@Aspect    // 定义一个切面
public class AgentProxy {// 声明前置通知@Before()public void doSkill() {System.out.println("我是经纪人,我会接代言,管粉丝!");}

通知:通知就是定义代理对象的代码要在什么时候生效。
以下是常用的通知类型,可以根据实际情况选用需要的通知:

注解通知
@Before通知方法会在目标方法调用之前执行
@After通知方法会在目标方法返回或异常后调用
@AfterReturning通知方法会在目标方法返回后调用
@AfterThrowing通知方法会在目标方法抛出异常后调用
@Around通知方法会在目标方法抛出异常后调用

  四、填写需要的切面表达式

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;@Component
@Aspect    // 定义一个切面
public class AgentProxy {/*** 切面表达式  *   调用返回值是void、Function这个类的sill()这个方法时就会生成对应的代理类*   切面表达式可以用通配符  **/@Before("execution(void  com.example.musicserver.test.Function.sill())")public void doSkill() {System.out.println("我是经纪人,我会接代言,管粉丝!(AOP实现!)");}


  切面表达式:定义了满足什么条件就去生成其代理类。

import com.example.musicserver.test.Function;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;@SpringBootApplication
public class MusicServerApplication {// 测试 AOP 前置通知public static void main(String[] args) {ConfigurableApplicationContext run = SpringApplication.run(MusicServerApplication.class, args);Function fun = (Function)run.getBean("actor");fun.sill();}}

 AOP的环绕通知:

最后在说一下AOP的环绕通知,环绕通知,可以说是使用最频繁的通知方式,会将整个方法包围起来,可以再目标方法执行前和执行后执行自己的逻辑代码。


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;@Component
@Aspect    // 定义一个切面
public class AgentProxy {/*** 环绕通知*   切面表达式:上面说到可以用通配符实现*              这里就是对com.example.musicserver.test路径所有方法进行拦截定义*/@Around("* com.example.musicserver.test.*.*()")public Object doSkill2(ProceedingJoinPoint pjp) {System.out.println("我是经纪人,正在接戏中。。。");Object proceed = null;try {//  这里需要我们执行拦截方法本身的代码(最后返回)proceed = pjp.proceed();} catch (Throwable throwable) {throwable.printStackTrace();}System.out.println("我是经纪人,演出结束,收钱!");return proceed;}}

ProceedingJoinPoint简单理解就是把原始方法封装起来,可以随时调用
环绕通知=前置逻辑+目标方法执行+后置逻辑执行,pjp的proceed方法就是用于目标方法的执行

注意:ProceedingJoinPoint.proceed() 返回的是目标方法执行后的返回值,一定要在环绕通知返回出去!!!

import com.example.musicserver.test.Function;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;@SpringBootApplication
public class MusicServerApplication {public static void main(String[] args) {// 环绕通知测试ConfigurableApplicationContext run = SpringApplication.run(MusicServerApplication.class, args);Function fun = (Function)run.getBean("actor");fun.sill();}}

SpringAOP的优势和缺点:

springAOP的优势很明显,在不改变原有代码的情况下,加入新的逻辑代码。
缺点是:逻辑不连贯,阅读体验不好。毕竟这是专门解决特定问题而出现的专用工具。
我们应该有一个意识,当我们需要批量给方法新增逻辑的时候,就能想到SpringAOP。

SpringAOP总结:

AOP是一种编程思想————面向切面编程
AOP实现原理————代理模式。 代理模式分为动态代理和静态代理。
SpringAOP使用步骤:1.导入依赖
                                    2.使用切面注解
                                    3.使用通知注解
                                    4.使用切点申明表达式

        java里面的概念很多,知识点也很多。很多概念和知识点是专为解决特定问题而诞生的,我们不可能记住全部知识点,但是在需要用到一个知识点的时候,要能想起什么知识点能解决这个问题,在不断的遇到问题,解决问题的过程中,我们对这些知识点的理解自然会更深刻,

更多推荐

SpringAOP —— 代理模式(记录使用方法)

本文发布于:2024-02-07 02:28:12,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1752309.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:使用方法   模式   SpringAOP

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!