这篇文章主要介绍了怎么使用抽象语法树AST实现一个AOP切面逻辑的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇怎么使用抽象语法树AST实现一个AOP切面逻辑文章都会有所收获,下面我们一起来看看吧。
将 js 文件下的全部方法添加一个开始事件和一个结束事件并传入方法名,以便监听某个方法的调用。
function eat(){
let food = "apple"
let time = '2小时'
return '吃' + food + '用时' + time
}
function work(){
}
console.log(eat())
控制台打印
可以看到,输入了执行 eat 方法的开始事件及结束事件。其实,这个过程就是 work.js 转成语法树后,对方法节点进行了处理,添加了两个切面方法:start 和 end 事件。
这个文件用来声明 start 和 end 事件。
function start(funcName){
console.log('开始执行:' + funcName + '方法')
}
function end(funcName){
console.log('执行结束:' + funcName + '方法')
}
//文件操作工具
const fs = require('fs');
//JS代码转语法树工具
const parser = require('./babel-core/node_modules/babylon');
//语法树遍历工具
const traverse = require('./babel-core/node_modules/babel-traverse');
//语法树转JS代码工具
const generator = require('./babel-core/node_modules/babel-generator');
//声明语法树类型工具
const t = require('./babel-core/node_modules/babel-types');
//获取aop代码
let aop = fs.readFileSync('./aop.js','utf-8')
//获取需要添加切面的代码
let content = fs.readFileSync('./work.js','utf-8')
//将需要添加切面的代码转换为语法树
let ast = parser.parse(content,{
sourceType:'script'
})
//遍历指定语法树时操作项(这里遍历的指定节点是FunctionDeclaration方法)
const visitor = {
FunctionDeclaration:({ node }) => {
//获取每个方法体里面的节点
let funcBody = node.body.body
//创建一个名为start,参数为当前方法名的执行节点,后面的参数为创建一个名为start方法的参数
let start = t.callExpression(t.identifier('start'), [t.identifier(`"${node.id.name}"`)])
//添加到方法的最前面
funcBody.unshift(start)
//判断最后一个节点是不是return,方式结束事件调用节点在最后无法调用。
let lastNode = funcBody.slice(-1)
//创建一个名为end,参数为当前方法名的执行节点,后面的参数为end方法的参数
let end = t.callExpression(t.identifier('end'), [t.identifier(`"${node.id.name}"`)])
//设定end节点添加的位置
let insertEndEventPosition = (funcBody.length)
if(lastNode[0].type == 'ReturnStatement'){
//放在return节点的前面
insertEndEventPosition -= 1
}
//添加end节点
funcBody.splice(insertEndEventPosition,0,end)
}
}
//开始遍历操作语法树
traverse.default(ast,visitor)
//将处理完的语法树再次转换为JS代码
let codeResult = generator.default(ast)
//这里需要添加aop里面的两个切面事件到最终的JS代码里。
let outFileCode = aop + '\n\n' + codeResult.code
// 写入文件操作
fs.mkdir('cache',(err)=>{
if(!err){
fs.writeFile('cache/main.js',outFileCode,(err)=>{
if(!err){
console.log('文件创建完成')
}
})
}
})
上面的代码执行完后,看下 main.js 生成的代码内容。
function start(funcName){
console.log('开始执行:' + funcName + '方法')
}
function end(funcName){
console.log('执行结束:' + funcName + '方法')
}
function eat() {
start("eat")
let food = "apple";
let time = '2小时';
end("eat")
return '吃' + food + '用时' + time;
}
function work() {
start("work")
end("work")
}
console.log(eat());
相比较之前的 work.js 文件,添加了两个切面方法的同时,保证每个方法都添加了 start 及 end 事件。这样再调用的时候便可直接在执行前后操作其他任务了。
关于“怎么使用抽象语法树AST实现一个AOP切面逻辑”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“怎么使用抽象语法树AST实现一个AOP切面逻辑”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注亿速云行业资讯频道。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
原文链接:https://juejin.cn/post/7198626040355668027