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 ...
随机推荐
- asp.net core 2.0 web api + Identity Server 4 + angular 5 可运行前后台源码
前台使用angular 5, 后台是asp.net core 2.0 web api + identity server 4. 从头编写asp.net core 2.0 web api 基础框架: 第 ...
- 错误提示:Access denied for user 'GC'@'localhost' (using password: YES)
错误描述:使用的是C3P0连接池 Spring整合Mybatis时出现错误 java.sql.SQLException: Access denied for user 'GC'@'localhost' ...
- pgrep - 命令
pgrep 命令格式:pgrep [选项] [模式] 选项 含义 -d <string> 指定输出分隔符 -l PID和进程名称 -a 列出PID和完整的命令行 -v 取反 -c 统计进程 ...
- Win10环境下YOLO5 快速配置与测试
目录 一.更换官方源 二.安装Pytorch+CUDA(python版本) 三.YOLO V5 配置与验证 四.数据集测试 五.小结 不想看前面,可以直接跳到标题: 一.更换官方源 在 YOLO V5 ...
- [Azure DevOps] 如何安装并配置 Build Agent
1. 编译服务器 在 Azure Pipelines 中至少需要一个编译服务器的 Agent 才能编译代码或发布软件.Azure DevOps 本身已经提供了一个 Agent,但出于各种理由(需要特殊 ...
- SpringBoot项目war包部署
服务部署 记录原因 将本地SpringBoot项目通过war包部署到虚拟机中,验证服务器部署. 使用war包是为了方便替换配置文件等. 工具 对象 版本 Spring Boot 2.4.0 VMwar ...
- Java(1-24)【前言、入门程序、常量、变量、类型转换】
如何输出规定结果,利用String.format System.out.println(String.format("%.2f", f)); 编译:是指将我们编写的Java源文件翻 ...
- Spring Cloud Gateway 扩展支持动态限流
之前分享过 一篇 <Spring Cloud Gateway 原生的接口限流该怎么玩>, 核心是依赖Spring Cloud Gateway 默认提供的限流过滤器来实现 原生Request ...
- 人生第一个扩展——Github1s
1 灵感 某天看到了一个叫github1s的仓库: 基于Node.JS.Yarn.Python等技术栈,在github.com上面加上"一秒",也就是github1s.com,就能 ...
- 这一次,彻底搞懂 Go Cond
hi,大家好,我是 haohongfan. 本篇文章会从源码角度去深入剖析下 sync.Cond.Go 日常开发中 sync.Cond 可能是我们用的较少的控制并发的手段,因为大部分场景下都被 Cha ...