5Spring动态代理开发小结
5Spring动态代理开发小结
1.为什么要有动态代理?
- 好处 - 1.利于程序维护
 2.利于原始类功能的增强
 3.得益于JDK或者CGlib等动态代理技术使得程序扩展性很强
 
- 为什么说使得程序扩展性很强? - 静态代理运行一个增强类需要编译为.class文件,再进入到虚拟机之中运行,如果增加一个功能,就需要重新编译文件造成维护上的灾难
 动态代理会使用JDK或者CGlib等动态代理技术在JVM直接生成字节码文件也称为动态字节码文件,直接可以在虚拟机中运行,且可以在不重新编译前提下运行
 
2.如何开发动态代理对象
1.MethodBeforeAdvice
1.需要原始对象,被代理对象(Target)
 被代理对象的接口
import org.User;
public interface UserService {
    //这个User只是象征性的传入个对象
    public void register(User user);
    public Boolean login(String name, String password);
}
 原始对象
import org.User;
public class UserServiceImpl implements UserService {
    @Override
    public void register(User user) {
        System.out.println("UserServiceImpl.register");
    }
    @Override
    public Boolean login(String name, String password) {
        System.out.println("UserServiceImpl.login "+name+" "+password );
        return true;
    }
}
2.编写额外功能,它实现MethodBeforeAdvice接口(增强类)
 实现MethodBeforeAdvice 的运行在目标类之前
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class UserPoxyBefore implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("UserPoxyBefore.before");
    }
}
 3.在配置文件定义切入点
 首先得实现原始类和增强类
  <bean id="UserServicePiont" class="org.Service.UserServiceImpl"/>
  <bean id="UserPoxyBefore" class="org.Service.UserPoxyBefore"  />
 再定义切入点
-  pointcut表示切入的地方,而里面的expression指定切入的方法,也就是使用这个增强类的地点
-  advisor指定用哪个增强类在哪个切入点
<aop:config  >
        <aop:pointcut id="UserPoxyPC" expression="execution(* *(..))"/>
        <aop:advisor advice-ref="UserPoxyBefore" pointcut-ref="UserPoxyPC"/>
    </aop:config>
3.调用
 调用时的注意事项可以看这个点这个
@Test
    public void test2() {
        ApplicationContext context=new ClassPathXmlApplicationContext("/ApplicationContext2.XML");
       UserService userService= (UserService) context.getBean("UserServicePiont");
        userService.login("SY", "123456");
        userService.register(new User());
    }
 结果,可见代理类确实使用了
UserPoxyBefore.before
UserServiceImpl.login SY 123456
UserPoxyBefore.before
UserServiceImpl.register
2.MethodInterceptor(方法拦截器)
实现的MethodInterceptor可以运行在原始方法前中后
1.实现MethodInterceptor接口
在前面准备好了原始类接着直接开发增强功能就好,开发步骤和上面的一致,只不过第二步变为实现MethodInterceptor接口,如下
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class Intercepter implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        return null;
    }
}
之后添加
- invocation.proceed() 基本低效为原始方法
		Object ret=invocation.proceed();
        System.out.println("Intercepter.invoke");//增强的功能
组装起来
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class Intercepter implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        Object ret=invocation.proceed();
        System.out.println("Intercepter.invoke");
        return ret;
    }
}
2.配置文件
实现Intercepter 即可,后续配置和上面一致
<bean id= "intercepter" class="org.Service.Intercepter"/>
<aop:config  >
        <aop:pointcut id="UserPoxyPC" expression="execution(* *(..))"/>
        <aop:advisor advice-ref="intercepter" pointcut-ref="UserPoxyPC"/>
    </aop:config>
3.运行
直接运行上面的调用代码,不用改动,也体现了程序扩展性
结果
UserServiceImpl.login SY 123456
Intercepter.invoke
UserServiceImpl.register
Intercepter.invoke
4.如何让运行intercepter在原始方法的任意位置
由于invocation.proceed() 基本低效为原始方法,所以只需要把invocation.proceed() 放在不同位置即可
如调换位置
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class Intercepter implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("Intercepter.invoke");
        Object ret=invocation.proceed();
        return ret;
    }
}
运行结果,可以看到运行位置不同了
Intercepter.invoke
UserServiceImpl.login SY 123456
Intercepter.invoke
UserServiceImpl.register
3.对MethodBeforeAdvice的before方法参数分析
对于before有三个参数
-  Method method
-  Object[] args
-  Object target
我们在它的接口实现设置断点

接着DEBUG 测试方法

看到method就是原始类的方法,也就是在配置文件定义的目标方法(pointcut里的expression)
args 就是原始类的方法传输的参数
target就是目标类,和JDK动态代理极其类似
接着继续DEBUG

情况和上面一样,User我没有注入数据所以为null
对于MethodInterceptor也大致相同,就不再过多分析
5Spring动态代理开发小结的更多相关文章
- Mybaits之Mapper动态代理开发
		Mybaits之Mapper动态代理开发 开发规范: Mapper接口开发方法只需要程序员与Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法 ... 
- java框架之MyBatis(1)-入门&动态代理开发
		前言 学MyBatis的原因 1.目前最主流的持久层框架为 Hibernate 与 MyBatis,而且国内公司目前使用 Mybatis 的要比 Hibernate 要多. 2.Hibernate 学 ... 
- MyBatis使用Mapper动态代理开发Dao层
		开发规范 Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同原始Dao接口实现类方法. Mappe ... 
- Mybatis框架三:DAO层开发、Mapper动态代理开发
		这里是最基本的搭建:http://www.cnblogs.com/xuyiqing/p/8600888.html 接下来做到了简单的增删改查:http://www.cnblogs.com/xuyiqi ... 
- MyBatis开发Dao的原始Dao开发和Mapper动态代理开发
		目录 咳咳...初学者看文字(Mapper接口开发四个规范)属实有点费劲,博主我就废了点劲做了如下图,方便理解: 原始Dao开发方式 1. 编写映射文件 3.编写Dao实现类 4.编写Dao测试 Ma ... 
- 一张图带你看懂原始dao与SQL动态代理开发的区别-Mybatis
		//转载请注明出处:https://www.cnblogs.com/nreg/p/11156167.html 1.项目结构区别: 2.开发区别: 注:其中原始dao开发的实现类UserDaoImpl ... 
- JavaWeb_(Mybatis框架)Mapper动态代理开发_三
		系列博文: JavaWeb_(Mybatis框架)JDBC操作数据库和Mybatis框架操作数据库区别_一 传送门 JavaWeb_(Mybatis框架)使用Mybatis对表进行增.删.改.查操作_ ... 
- MyBatis - Mapper动态代理开发
		Mapper接口开发方法编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象. Mapper接口开发方式是基于入门程序的基础上,对 控制程序 进行分层开发, ... 
- MyBatis 动态代理开发
		MyBatis 动态代理开发 § Mapper.xml文件中的namespace与mapper接口的类路径相同. § Mapper接口方法名和Mapper.xml中定义的每个statement的i ... 
随机推荐
- Android 之 ToolBar 踩坑笔记
			写在前面 •前言 这两天,学完了 Fragment 的基础知识,正准备跟着<第一行代码>学习制作一个简易版的新闻应用: 嘀嘀嘀~~~ 一声消息传来,像往常一样,打开 QQ,当我看到 QQ ... 
- vue 快速入门 系列 —— 侦测数据的变化 - [基本实现]
			其他章节请看: vue 快速入门 系列 侦测数据的变化 - [基本实现] 在 初步认识 vue 这篇文章的 hello-world 示例中,我们通过修改数据(app.seen = false),页面中 ... 
- maven中心仓库OSSRH使用简介
			目录 简介 为什么使用中心仓库 发布到中心仓库前的准备工作 使用OSSRH 使用Sonatype创建ticket 中央仓库中的组件要求 提供Javadoc 和源代码 使用GPG/PGP给文件签名 Me ... 
- LibTorch实战六:C++版本YOLOV5.4的部署
			一.环境配置 win10 vs2017 libtorch-win-shared-with-deps-debug-1.8.1+cpu opencv349 由于yolov5代码,作者还在更新(写这篇博客的 ... 
- BUAA_2021_SE_READING_#2
			项目 内容 这个作业属于哪个课程 2021春季软件工程(罗杰 任健) 这个作业的要求在哪里 个人阅读作业#2 我在这个课程的目标是 通过课程学习,完成第一个可以称之为"软件"的项目 ... 
- Git版本控制之-创建配置本地git仓库
			查看全局配置:code .gitconfig [code 就代表的用vscode 打开gitconfig 文件,如果是 sublime 就是 subl ][如果打开失败说明环境变量没有配置] [只有配 ... 
- 【笔记】《Redis设计与实现》chapter19 事务
			chapter19 事务 Redis通过MULTI.EXEC.WATCH等命令来实现事务功能 19.1 事务的实现 事务开始 redis> MULTI ok 通过切换客户端状态的flag属性的R ... 
- manjaro 手动调节屏幕亮度
			1 问题描述 manjaro版本20.0,桌面XFCE,设置之类的地方没有屏幕亮度调节的功能. 2 解决方案 解决方案来自arch wiki. 亮度由ACPI内核模块控制,这个模块的接口在以下位置: ... 
- 由电脑专卖系统引发的Java设计模式:访问者模式
			目录 定义 意图 解决问题 何时使用 优缺点 结构 电脑专卖系统 定义 访问者模式是对象的行为型模式,它的目的是封装一些施加于某些数据结构元素之上的操作,一旦这些操作需要修改的话,接收这个操作的数据结 ... 
- qsort  快排函数(C语言)
			qsort 快排函数(C语言) 函数原型 void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, ... 
