java架构解密——实时动态aop
在上篇博客中个。咱们一起组建了一个容器,里面封装了业务,这样,咱们就将业务和服务的组装放到了client,而client就相当于咱们的开发中使用到的配置文件。大家发现问题了吗?就是我不能动态修改了?业务容器在代理完毕后,又一次加入一个容器。这时候。是不被同意的,那这个容器就是个编译时起作用的容器,他就丧失了非常多的灵活性。
那怎么办呢?实际就是调换一下调用顺序就好。大家看看结果:
1,类图对照
改造后类图
2,代码实现:
2.1代理类的变化:
/**
* 打招呼动态代理类,给业务类加入功能
* 前一版本号为JDK代理实现
* 本次加入运行方法之前打印到控制台‘befor’
* 本次加入运行方法之后打印到控制台‘after’
*本次版本号为DGLIB代理
* 换代理类原因,JDK代理要求被代理类必须实现某接口,由于它底层实现是新建一个类,实现和被代理类同样的接口
* 用代理类新建的业务类代替原业务类
* CGLIB代理是新建一个类。继承自被代理类,用新建的代理类替换掉原业务类,就不须要接口了
*
*5.0版本号添加服务组装容器,将服务从代理类中抽离出去了,我们的代理类成为了一个bean
*6.0将服务容器定义为接口
*7.0添加业务容器
*8.0 业务容器不灵活,将获代替理放置到业务容器端,实现动态添加元素,也能拿到代理
* @author 许恕
* @version 3.0.0 , 2015年6月16日 下午3:20:13
*/
public class CGLibDynamicProxy implements MethodInterceptor {
//服务类容器
private IProxyMehds proxyMehds;
//代理工厂类:单例模式,优化内存开销
private static CGLibDynamicProxy instance = new CGLibDynamicProxy();
//构造函数
private CGLibDynamicProxy() {
}
//获取cglib代理工厂类
public static CGLibDynamicProxy getInstance() {
return instance;
}
/**
* 使用代理工厂生成某个类的代理
*
* @param cls 要代理的类
* @return 返回已经代理好的类
*/
@SuppressWarnings("unchecked")
public <T> T getProxy(Class<T> cls) {
return (T) Enhancer.create(cls, this);
}
//重写被代理对象的方法运行
//全部的方法运行。到反射的级别都是invoke,重写了这种方法,就重写了全部的方法运行,实现了代理
@Override
public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable {
//重要改进:从服务容器中运行方法,不再是写死的!
proxyMehds.beforeBean();
//方法正常运行的语句
Object result = proxy.invokeSuper(target, args);
//重要改进:从服务容器中运行方法。不再是写死的!
proxyMehds.afterBean();
return result;
}
//服务容器的get方法
public IProxyMehds getProxyMehds() {
return proxyMehds;
}
//服务容器的set方法
public void setProxyMehds(IProxyMehds proxyMehds) {
this.proxyMehds = proxyMehds;
}
}
2.2业务容器
/**
* 业务类容器:
* 用map盛放要切入服务的业务类
*
* @author 许恕
* @version 3.0.0 , 2015-6-29 14:25:21
*/
public class DoMehds implements IDoMehds {
//盛放运行业务的map
private HashMap<String,Object> DoBeans;
//代理类
private CGLibDynamicProxy proxy ;
/**
* 封装获取元素的方法。每次获取元素都封装一个代理
*
* @param 元素的名字
* @return 代理好的元素
*/
public Object getBean(String beanName){
return proxy.getProxy(DoBeans.get(beanName).getClass());
}
//获取业务map
public HashMap<String, Object> getDoBeans() {
return DoBeans;
}
//设置业务map
public void setDoBeans(HashMap<String, Object> doBeans) {
DoBeans = doBeans;
}
//获代替理类
public CGLibDynamicProxy getProxy() {
return proxy;
}
//设置代理类
public void setProxy(CGLibDynamicProxy proxy) {
this.proxy = proxy;
}
}
2.3 client
/**
* 运行代理程序的client
*
* @author 许恕
* @version 3.0.0 , 2015年6月16日 下午3:18:42
*/
public class Client {
//client运行的主方法:系统规定
public static void main(String[] args) {
//盛放方法运行前的对象的容器
HashMap<String,Object> beforBeans;
HashMap<String,Object> afterBeans;
//配制方法运行前要运行哪些方法
HashMap<String,String> beforMethods;
HashMap<String,String> afterMethods;
//实例以上定义的服务类map
beforMethods=new HashMap();
beforBeans=new HashMap();
afterMethods=new HashMap();
afterBeans=new HashMap();
//将服务类AspectClass1加入到方法运行要载入的服务类
beforBeans.put("AspectClass1", new AspectClass1());
beforBeans.put("AspectClass2", new AspectClass2());
afterBeans.put("AspectClass3", new AspectClass3());
afterBeans.put("AspectClass4", new AspectClass4());
//规定每一个服务类要运行的方法
beforMethods.put("AspectClass1", "SayHello");
beforMethods.put("AspectClass2", "SayGoodBye");
afterMethods.put("AspectClass3", "SayHi");
afterMethods.put("AspectClass4", "Eat");
//实例服务类容器。将四个map传入容器中
ProxyMehds proxyMehds =new ProxyMehds();
proxyMehds.setBeforBeans(beforBeans);
proxyMehds.setBeforMethods(beforMethods);
proxyMehds.setAfterBeans(afterBeans);
proxyMehds.setAfterMethods(afterMethods);
//实例业务map
HashMap<String,Object> DoBeansMap = new HashMap<String,Object> ();
//将业务装载到map中
DoBeansMap.put("dobeans1", new GreetingImpl());
DoBeansMap.put("dobeans2", new EatClass());
//将业务map装载到容器中
DoMehds doMehds = new DoMehds();
doMehds.setDoBeans(DoBeansMap);
//实例代理类
CGLibDynamicProxy cglib =CGLibDynamicProxy.getInstance();
//接受切面
cglib.setProxyMehds(proxyMehds);
doMehds.setProxy(cglib);
//接受要代理的对象
Greeting greeting = (Greeting)doMehds.getBean("dobeans1");
EatClass eatObject = (EatClass)doMehds.getBean("dobeans2");
//运行对象的某个方法
greeting.sayHello("Jack");
eatObject.Eat();
}
}
3。总结
代码的灵活,就像生活一般。在代码灵活的过程中。我们就会对照下生活,生活中。我们每一个人,事。物都是独立的对象。而在生活中的时间轴中。我们也是过程化的组织,我们的代码和生活。在思想上都是同样的。优化的不不过代码,还有思想啊。
java架构解密——实时动态aop的更多相关文章
- 最新咕咆+鲁班+图灵+享学+蚂蚁+硅谷+源码 Java架构师资料《Java架构师VIP课程》
最新的Java架构师完整资料,完整视频+源码+文档. 每一套都是一百多个G的资料,无密. JAVA架构师全套课程 咕泡学院互联网架构师第一期 咕泡学院互联网架构师第二期 咕泡学院互联网架构师第三期 博 ...
- paip.java 架构师之路以及java高级技术
paip.java 架构师之路以及java高级技术 1. Annotation 设计模式... 概念满天飞.ORM,IOC,AOP. Validator lambda4j memcache. 对 ...
- JAVA架构师要求
JAVA架构师要求专业素质要求:1.理解架构师的职责和架构设计的目标.原则及取舍:2.精通架构模式,Transaction.Security.Persistence等机制及实现,IOC.AOP.SOA ...
- 一位资深Java架构师的晋级心得
架构师是什么? 是一个既需要掌控整体又需要洞悉局部瓶颈并依据具体的业务场景给出解决方案的团队领导型人物.一个架构师得需要足够的想像力,能把各种目标需求进行不同维度的扩展,为目标客户提供更为全面的需求清 ...
- JAVA架构师面试题 一
基础题目 Java线程的状态 进程和线程的区别,进程间如何通讯,线程间如何通讯 HashMap的数据结构是什么?如何实现的.和HashTable,ConcurrentHashMap的区别 Cookie ...
- Java架构师之路 Spring学习笔记(一) Spring介绍
前言 这是一篇原创的Spring学习笔记.主要记录我学习Spring4.0的过程.本人有四年的Java Web开发经验,最近在面试中遇到面试官总会问一些简单但我不会的Java问题,让我觉得有必要重新审 ...
- Java架构师必会的技能
Java架构师必会的技能 我把它分为了五大专题 工程化专题 工程化专题 git git安装使用 git日常使用:fetch/pull/push/revert/rebase git分支管理git flo ...
- Java 架构师面试题
基础题目 Java线程的状态 进程和线程的区别,进程间如何通讯,线程间如何通讯 HashMap的数据结构是什么?如何实现的.和HashTable,ConcurrentHashMap的区别 Cookie ...
- Java架构师必看,超详细的架构师知识点分享!
在Java程序员行业中,有不少Java开发人员的理想是成为一名优秀的Java架构师,Java架构师的主要任务不是从事具体的软件程序的编写,而是从事更高层次的开发构架工作.他必须对开发技术非常了解,并且 ...
随机推荐
- USACO Ski Course Design解析和C语言实现
题目大意: John农场有N(1=<N<=1000)小丘陵(山),它们高度的范围从0 到 100 但仅仅有当最大的高度差不大于17时.才干够避税.John对它们进行改造,从高的丘陵上取土放 ...
- 创建一个Spring的HelloWorld程序
Spring IOC IOC指的是控制反转,把对象的创建.初始化.销毁等工作都交给Spring容器.由spring容器来控制对象的生命周期.下图能够说明我们传统创建类的方式和使用Spring之后的差别 ...
- [NOIP2015模拟10.27] 挑竹签 解题报告(拓扑排序)
Description 挑竹签——小时候的游戏夏夜,早苗和诹访子在月光下玩起了挑竹签这一经典的游戏.挑竹签,就是在桌上摆上一把竹签,每次从最上层挑走一根竹签.如果动了其他的竹签,就要换对手来挑.在所有 ...
- 求推荐go语言开发工具及go语言应该以哪种目录结构组织代码?
go语言的开发工具推荐? go语言开发普通程序及开发web程序的时候,应该以哪种目录结构组织代码? 求推荐go语言开发工具及go语言应该以哪种目录结构组织代码? >> golang这个答案 ...
- vuejs on
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- git 和github 关联
创建本地仓库: 查看本地仓库配置信息: 如果没有配置,则进行配置: git config --global user.name "这里换上你的用户名" git config --g ...
- phpstorm10安装并汉化
一.下载phpstorm 下载地址:https://pan.baidu.com/s/1R64ZROVP1ljGbYfCwWjwxA 二.一直点击下一步安装即可 注意:第3步的时候选择一下支持的后缀 三 ...
- 部分vivo和oppo手机,使用上传图片功能,可能会出现退出webview的现象(回退到app的入口页面)
在公司的app里面嵌入了一个h5页面,h5页面有个使用图片上传功能,上传图片出现闪退的现象 问题描述:vivo手机,在app内的wap页面使用上传图片的功能,在选择好图片点击确认按钮后,出现退出整个w ...
- Raspberry Pi - 调整你的SD卡分割区的大小
在使用Win32DiskImager为一张空白的SD卡刷入新的Rasbian系统后,卡上的可用剩余空间并不大, 本人有一张8G的SD卡,但是刷入4.1的Rasbian后,用df -h查看,根目录下的空 ...
- 题解 P2504 【[HAOI2006]聪明的猴子】
这道题要坑死人啊... 第一次做40分,其他RE,改了一次之后就变成20分了... 究其原因,是有一个数组(dis)开的太小了,于是最后本蒟蒻就随手开了个五百万,然后,就AC了. 看到有一篇题解说求距 ...