1、代理模式

为什么要学习代理模式?因为这就是Spring AOP 的底层 !【SrpingAOP 和 SpringMVC】这两个面试重点!

​ 代理模式分类:

  • 静态代理

  • 动态代理

1.1静态代理

角色分析:

  • 抽象角色:一般会使用接口或抽象类来解决
  • 真实角色:被代理的角色
  • 代理角色:代理真实角色,代理真实角色后,我们一般会做一些附属操作
  • 客户:访问代理对象的人!

代码步骤:

  1. 接口
//租房
public interface Rent {public void rent();
}
  1. 真实角色
//房东
public class Host implements Rent {public void rent() {System.out.println("房东要出租房子!");}
}
  1. 代理角色
public class Proxy implements Rent {private Host host;public Proxy() {}public Proxy(Host host) {this.host = host;}public void rent() {seeHouse();host.rent();hetong();fare();}//看房public void seeHouse(){System.out.println("中介带你看房!");}//合同public void hetong(){System.out.println("签租赁合同");}//收中介费public void fare(){System.out.println("收中介费!");}
}
  1. 客户端访问代理角色
public class Client {public static void main(String[] args) {//房东要出租房子Host host=new Host();//代理,中介帮房东出租房子,但是呢,代理角色一般会有一些附属操作Proxy proxy = new Proxy(host);//你不用面对房东,直接找中介租房即可proxy.rent();}
}

代理模式的好处:

  • 可以使真实角色的操作更加纯粹!不用去关注一些公共的业务!
  • 公共业务就交给了代理角色!实现了业务的分工!
  • 公共业务发生拓展的时候,方便集中管理!

缺点:

  • 一个真实角色就会产生一个代理角色;代码量会翻倍,开发效率会变低

1.2、动态代理

  • 动态代理和静态代理角色一样
  • 动态代理的代理类是动态生成的,不是我们直接写好的
  • 动态代理分为两大类:基于接口的动态代理,基于动态类的动态代理
    • 基于接口的----JDK的动态代理【我们在这里使用】
    • 基于类:cglib
    • Java字节码实现:Javassist

需要了解两个类:Proxy:代理,InvocationHandler:调用处理程序

  1. 接口
//租房
public interface Rent {public void rent();
}
  1. 真实角色
//房东
public class Host implements Rent {public void rent() {System.out.println("房东要出租房子!");}
}
  1. 代理角色
package com.gzh.demo02;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;//我们用这个类自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {//被代理的接口private Rent rent;public void setRent(Rent rent) {this.rent = rent;}//生成得到代理类public Object getProxy(){return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);}//处理代理实例,并返回结果public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {seeHouse();//动态代理的本质,就是使用反射机制实现System.out.println(args);Object result = method.invoke(rent, args);hetong();fare();return result;}//看房public void seeHouse(){System.out.println("中介带你看房!");}//合同public void hetong(){System.out.println("签租赁合同");}//收中介费public void fare(){System.out.println("收中介费!");}
}
  1. 客户端访问代理角色
public class Client {public static void main(String[] args) {//真实角色Host host=new Host();//代理角色ProxyInvocationHandler pih = new ProxyInvocationHandler();//通过调用程序处理角色来处理我们要调用的接口对象!pih.setRent(host);Rent proxy = (Rent) pih.getProxy();//这里的proxy是动态生成的,我们并没有写proxy.rent();}
}

动态代理的好处:

  • 可以使真实角色的操作更加纯粹!不用去关注一些公共的业务!
  • 公共业务就交给了代理角色!实现了业务的分工!
  • 公共业务发生拓展的时候,方便集中管理!
  • 一个动态代理类代理的是一个接口,一般就是对应的一类业务
  • 一个动态代理类可以代理多个类,只要是实现了同一个接口即可

2.AOP

2.1什么是AOP

AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一

维护的一种技术。AOP是OOP的延续,是软件开发的一个热点,也是Spring框架的一个很重要的内容,是函数式编程的

一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各个部分之间的耦合度降低,提高程序

的可重用性,同时提高了开发的效率。

2.2 AOP在Spring中的作用

提供声明式事物;允许用户自定义切面

  • 横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分

    就是横切关注点。如日志,安全,缓存,事物等等。。。

  • 切面(ASPECT):横切面关注点 被模块化 的特殊对象。即,它是一个类

  • 通知(Advice):切面必须要完成的工作,即,它是一个方法

  • 目标(Target):被通知对象

  • 代理(Proxy):向目标对象应用通知之后创建的对象

  • 切入点(PointCut):切面通知执行的 ”地点“ 的定义

  • 连接点(Jo’i’ntPoint):与切入点匹配的执行点

2.3 使用Spring实现AOP

【重点】使用AOP,先导入个依赖

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.5</version></dependency>

方式一:使用Spring的API接口【主要是SPring接口实现】

  • 测试方法接口
public interface UserService {public void add();public void delete();public void update();public void select();
}
  • 实现类
public class UserServiceImpl implements UserService {public void add() {System.out.println("新增了一个用户");}public void delete() {System.out.println("删除了一个用户");}public void update() {System.out.println("修改了一个用户");}public void select() {System.out.println("查询了一个用户");}
}
  • 执行前类
public class Log implements MethodBeforeAdvice {//method:要执行的目标对象的方法//args:参数//target:目标对象public void before(Method method, Object[] args, Object target) throws Throwable {System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了");}
}
  • 执行后类
public class AfterLog implements AfterReturningAdvice {public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {System.out.println("执行了"+target.getClass().getName()+"的"+method.getName()+"方法,返回结果为:"+returnValue);}
}
  • bean
    <bean id="userService" class="com.gzh.service.Impl.UserServiceImpl"/><bean id="log" class="com.gzh.log.Log"/><bean id="afterLog" class="com.gzh.log.AfterLog"/><!--方式一:使用原生Spring API接口--><!--配置AOP:需要导入aop的约束--><aop:config><!--切入点:expression:表达式--><aop:pointcut id="pointuct" expression="execution(* com.gzh.service.*.*(..))"/><!--执行环绕增加--><aop:advisor advice-ref="log" pointcut-ref="pointuct"/><aop:advisor advice-ref="afterLog" pointcut-ref="pointuct"/></aop:config>
  • 测试类
public class MyTest {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("applictionContext.xml");UserService userService = context.getBean("userService", UserService.class);userService.add();Sington sington = Sington.newInstant();sington.show();}
}

方式二:自定义类来实现AOP 【主要是切面定义】

  • 测试方法接口
public interface UserService {public void add();public void delete();public void update();public void select();
}
  • 实现类
public class UserServiceImpl implements UserService {public void add() {System.out.println("新增了一个用户");}public void delete() {System.out.println("删除了一个用户");}public void update() {System.out.println("修改了一个用户");}public void select() {System.out.println("查询了一个用户");}
}
  • 切面类
public class DiyPointCut {public void before(){System.out.println("方法执行前");}public void after(){System.out.println("方法执行后");}
}
  • bean
    <bean id="userService" class="com.gzh.service.Impl.UserServiceImpl"/>
<!--    方式二:自定义类--><bean id="diy" class="com.gzh.diy.DiyPointCut"/><aop:config><!--        自定义切面ref要引用的类--><aop:aspect ref="diy"><aop:pointcut id="pointuct" expression="execution(* com.gzh.service.*.*(..))"/><aop:before method="before" pointcut-ref="pointuct"/><aop:after method="after" pointcut-ref="pointuct"/></aop:aspect></aop:config>
  • 测试类
public class MyTest {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("applictionContext.xml");UserService userService = context.getBean("userService", UserService.class);userService.select();}
}

方式三:使用注解实现!【注意要开启注解支持】

方法接口和以上两个一样

  • 切面类
package com.gzh.diy;import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.context.annotation.Bean;//方式三:使用注解实现AOP
@Aspect //标注这一个类为一个切面
public class AnnotationPointCut {@Before("execution(* com.gzh.service.*.*(..))")public void before(){System.out.println("方法执行前");}@After("execution(* com.gzh.service.*.*(..))")public void after(){System.out.println("方法执行后");}//在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点@Around("execution(* com.gzh.service.*.*(..))")public void around(ProceedingJoinPoint jp) throws Throwable {System.out.println("环绕前");Signature signature = jp.getSignature();//获得签名System.out.println("signature:"+signature);//执行方法Object proceed = jp.proceed();System.out.println("环绕后");System.out.println(proceed);}
}

注意@Before和@After都是在aspectj.lang.annotation下的,不要导错了

  • bean
 <bean id="userService" class="com.gzh.service.Impl.UserServiceImpl"/>
<!--    方式三:注解实现AOP--><bean id="annotationPointCut" class="com.gzh.diy.AnnotationPointCut"/>
<!--     开启注解支持 JDK(默认 proxy-target-class="false") cglib(proxy-target-class="true")--><aop:aspectj-autoproxy proxy-target-class="false"/>
  • 测试类
public class MyTest {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("applictionContext.xml");UserService userService = context.getBean("userService", UserService.class);userService.select();}
}

代理模式与三种方式实现SpringAOP!相关推荐

  1. php简单记账本_代理记账的三种方式

    代理记账是指将本企业的会计核算.记账.报税等一系列的会计工作全部委托给专业记账公司完成,本企业只设立出纳人员,负责日常货币收支业务和财产保管等工作.一般来说 代理记账 业务主要分为三个方面分别是专项代 ...

  2. DM数据库开启归档模式的三种方式

    在生产和测试环境中,为了保证数据库的安全性,我们经常需要开启数据库为归档模式,达梦数据库开启归档模式的方式有多种,本章主要介绍开启归档模式的相关方法和常用数据字典. 检查数据库环境是否是归档模式 在开 ...

  3. 设置word只读模式的三种方式,分别如何取消只读模式?

    word文件可以设置只读模式,但是设置只读模式的方法不止有一种,今天和大家分享三种方式: 方式一: 这种只读模式仅起到提示功能,只是在打开文件时提示他人作者希望以只读方式打开,但是打开文件之后,我们还 ...

  4. hadoop组件---spark理论----spark on k8s模式的三种方式全面了解

    我们在之前的文章中 已经了解了 spark支持的模式,其中一种就是 使用k8s进行管理. hadoop组件-spark----全面了解spark以及与hadoop的区别 是时候考虑让你的 Spark ...

  5. shell进入特权模式_GRUB引导下进Linux单用户模式的三种方式,修改root密码

    versace handbags ;ro root=/dev/VolGroup00/LogVol00 rhgb quiet 修改成 : grub append>ro root=/dev/VolG ...

  6. java责任链模式的三种方式,分享一点面试小经验

    字节跳动 ⾯试前 ⼀⾯ ⼆⾯ ⼩结 ⾯试前 头条的⾯试是三家⾥最专业的,每次⾯试前有专⻔的HR和你约时间,确定OK后再进⾏⾯试.每次都是通过视频⾯试,因为都是之前都是电话⾯或现场⾯,所以视频⾯试还是有 ...

  7. 进入网页页面的开发者模式——三种方式

    1.什么是开发者模式:用来调试HTML,js等web内容的工具,就是开发者工具,我们可以通过开发者工具看到web页面的HTML,JS,以及浏览器的网络请求,CSS样式,内存使用等. 2.进入开发者模式 ...

  8. java bean 工厂模式_Spring框架通过工厂创建Bean的三种方式实现

    工厂模式 Spring中bean的创建,默认是框架利用反射new出来的bean实例.有时候也会有一些复杂的情况. 假设有一个飞机,属性如下,现在需要造很多同型号的飞机,那么唯一需要改变的属性只有Dri ...

  9. 课程介绍 复习 创建对象的三种方式 自定义构造函数创建对象 工厂模式创建对象

    课程介绍 <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8 ...

最新文章

  1. NOIP2008传纸条[DP]
  2. 深入理解position:relative 与 position:absolute(divb相对于diva进行绝对定位)
  3. mysql 选择特定的表_MySQL选择具有多个特定列的所有表
  4. 3.1_21 JavaSE入门 P20 【正则】Pattern模式类、Matcher匹配器、元字符、分组捕获、反向引用
  5. oracle性质是渐进正态性,基于惩罚函数的回归量变选择方法.doc
  6. 解决网络正常,但chrome浏览器无法正常使用的问题
  7. 聊天记录怎么录视频 微信聊天记录屏幕录制
  8. c语言合法浮点数,c语言中什么是浮点数
  9. 罗升阳:那两年炼就的Android内功修养(转载老罗的)
  10. HTML最给力的入门教程
  11. ubuntu18.04 安装Adobe Flash Player
  12. Arduino温度传感器全系列使用详解
  13. 证券基础知识——一手代表多少数量?
  14. 计算机图形学--中点椭圆算法原理及代码实现
  15. LCD1602显示屏原理及使用教程
  16. Ubuntu18.04 分屏显示问题解决
  17. 强制 code review:reviewboard+svn 的方案
  18. 2015.3 有n个小朋友围城一圈,玩击鼓传花游戏
  19. 钢琴软件c语言源代码,源代码.c · lijialong1313/C语言钢琴 - Gitee.com
  20. php登录用户名可以用中文吗,用户名是什么

热门文章

  1. 物联网IoT应用技术有哪些?
  2. 支持全球游戏加速 飞鱼星发烧级玩家路由G7上市
  3. codeforces 571A Lengthening Sticks 组合数学 插板法
  4. 浅谈研究生对科研工作的那些认知误区
  5. 2023湖南农业大学计算机考研信息汇总
  6. Emoji表情后台处理
  7. OpenFoam编程笔记——starccm网格转openfoam格式
  8. rem适配布局 Less基础 插件 cssrem
  9. 第六章 DDL语言
  10. JAVA:正则表达式(入门)