`

关于JAVA注解的一个梦想--使用注解实现缓存切面

    博客分类:
  • JDK
阅读更多
最近在做一个项目的时候,用到了业务自已的缓存,发现有很多这样的代码:
public List<User> findUsers(String userName){
Object result = getFromCache(createKey(userName));
if(result!=null){
     return result;
}
.....
result = userDAO.findData(userName);
putToCache(createKey(userName));
return result;
}

这几行是非常死的东西,除了key之外,到处都是一样,于是想到用SPRING的AOP注解来寻求解决方法,同时看了一些有关注解的文章,发现很难在AOP中取得所需要的KEY,因为生成KEY的方法基本都不一样,目标方法参数的个数和未知的类型也导致难以统一生成KEY。自定义注解也不能直接实现在方法的前后进行拦截,下面是我没有实现的想法:
private String createKey(String userName){
       return "user_List_Cache"+userName;
}

//注解的第一个参数是上面的方法,第二参数调用那个方法所需要的参数
//注解现在没有传递方法,也没法传递运行时的值--据我所知
@cache(keyMthod=createKey,keyPara=userName);
public List<User> findUsers(String userName){
//注解帮我在方法的前后进行调用注解类里的方法,我在注解类里写那死代码,
//这样这里就只需要写查询的逻辑,从数据库返回结果就行
......
return userDAO.findData(userName);
}


我的梦想:java注解类可以有方法实现,当上面的findUsers被执行时,注解类的某个方法会在方法执行前被调用,另一个方法会在之后被调用,且能方便的从当前运行环境中取得所需的对象和值。

提两个问题

1、我最上面的那段代码各位有什么更好的实现吗?请赐教
2、JAVA其实要支持这种注解也不难,为什么注解不做更强大一些,还是本来就可以,是我没发现?

补充一点,感谢很多朋友发表自已的意见,但有不少的朋友忽略我不能违背的一些条件:
1、使用SPRING的AOP意见,请考虑在类类内部调用时如何处理。
2、createKey方法的名字和参数不是固定的,每个业务类都可能不一样,而且有可能一个类有多个这样的方法。



欢迎讨论,但不要人身攻击......

###############10年以后更新#############2021-01-15 20:35
没想到,10年以后我真的还在写代码,偶然想起来当年有这样的想法还没有实现,今天这个实现方案,应该早在当年就具备外部条件了,奈何没有发现,今天偶然想起,果然只用了半天实现了,当年可能不具备的条件是,实际运行时可能取不到被拦截方法的真实参数名,在JDK1.8以前,可能只能取到arg0,arg1...这种,但不是必须的,有则更好而已
@LocalCache(keyPaths = {"system","bizType"})
public Object queryConfigs(String system, String bizType) {
       // 这里只管查数据库或者调远程读接口,随意。。。
       return queryDB()....
}

主要思想这里说下:
1、基于LocalCache注解先实现一个AOP切面;
2、切面执行时,可以取出注解的配置,这里这个配置就是被拦截方法的参数名,然后根据名称,取得拦截方法的运行时参数值,拼装成key,然后去取缓存,
3、如果取到,则返回,不再调用被拦截方法,如果取不到,则调用被拦截方法,并且把结果放入缓存。
分享到:
评论
5 楼 一粒蛋 2009-10-24  
因为出现的次数多,所以能省很多行。
老实说如果一共只省一两行,你改成 annotation 就是蛋疼。(啊!)

另外,万一写完发现更长更耗时间更不好改呢?……
我觉得批量替换更 KISS ……

/*xyz821*/Object result = getFromCache(key);  
if(result!=null){  
  return result;  
}


注:添上的注释 /*xyz821*/ 内容自定,作用是可以使批量替换不会误杀 …… 非常 stupid,不过很有效 ……

另外一个思路就是 AOP getFromCache(),(有时还能让编译器自动把 234 行的判断优化掉)。
不过我不喜欢 AOP,不想告诉你。
4 楼 lgdlgd 2009-10-24  
一粒蛋 写道
一次定义完所有 find_xxxs :(可能对于没接触过 ruby 的有点不好懂)
def method_missing(method, name)
  if method.to_s =~ /find_(\w+)s/
    cache[name] ||= const_get($1.capitalize).find(name)
  else
    raise 'method not found'
  end
end

这就和JAVA代理是差不多吧,当参数不只一个,而且只是其中某一部份作为缓存的KEY时,每个方法是哪一部都不确定,用你的思路能实现吗?
3 楼 一粒蛋 2009-10-24  
你这个需要,可能用动态代理比 annotation 更容易 ……

继续跑题 …… 一次定义完所有 find_xxxs :(可能对于没接触过 ruby 的有点不好懂)
def method_missing(method, *params)
  if method.to_s =~ /find_(\w+)s/
    cache[params] ||= const_get($1.capitalize).find(*params) # params 可多个
  else
    raise 'method not found'
  end
end


或者
def self.cached *methods
  @old_m ||= {}
  methods.each {|m|
    @old_m[m] = method(m)
    define_method(m){|params|
      cache[params] ||= old_m[params]
    }
  }
end
# 现在可以方便的用一行定义哪些要 cache,哪些不要 cache:
cached :find_users, :find_roles
2 楼 lgdlgd 2009-10-24  
一粒蛋 写道
更好的实现:
def find_users(name)
  cache[name] ||= User.find(name)
end


按你的说法,查询角色时,是不是也要这样?
def find_roles(name)  
  cache[name] ||= Role.find(name)  
end 
如果是这样,你只是少一两行代码,不是我想要的实现思路,我想法是在具实现中不出现这样的代码
1 楼 一粒蛋 2009-10-24  
更好的实现:
def find_users(name)
  cache[name] ||= User.find(name)
end

相关推荐

    Spring基于注解的缓存配置--web应用实例

    在本实例中,我们将深入探讨如何在Spring框架中利用注解来实现缓存配置,特别是在Web应用程序中的实际应用。Spring Cache是一个强大的功能,它允许我们高效地管理应用程序中的数据,减少不必要的数据库查询,提高...

    Java 使用注解拼接SQL语句

    "Java使用注解拼接SQL语句"是一个常见的实践,它使得动态构建SQL查询变得更为简洁和可维护。这种技术通常与ORM(对象关系映射)框架如MyBatis或Hibernate结合使用,但也可以通过自定义处理逻辑实现。 1. **自定义...

    自定义注解实现缓存机制

    创建一个类,比如`CacheAspect`,并使用`@Aspect`和`@Component`注解标记为切面组件。在这个切面中,我们将处理`@CacheResult`注解的方法调用,实现缓存逻辑: ```java import org.aspectj.lang....

    aop切面注解-限流与防止重复提交-2.docx

    AOP 切面注解 - 限流与防止重复提交是基于 AOP 编程范式实现的,使用了 FrequentlyRepetition 注解和 FrequentlyRepetitionAspect 切面。该实现可以防止重复提交和限流,提高系统的安全性和性能。

    spring4基于java注解事例

    在本教程中,我们将深入探讨如何使用Spring 4框架,特别是其基于Java注解的配置方式,来构建一个高效、可维护的系统。Spring 4是Java企业级应用开发的首选框架,它提供了广泛的功能,包括依赖注入、AOP(面向切面...

    SpringBoot使用注解实现 Redis 数据库的切换.zip

    在现代的Web应用程序开发中,SpringBoot框架因其简化配置、快速启动和强大的功能而...在实际开发中,还可以结合Spring的其他特性,如AOP(面向切面编程)来实现更复杂的逻辑,比如在特定的请求条件下自动切换数据库。

    spring整合redis做缓存用注解实现的完整例子

    Redis是一种高性能的键值数据存储系统,常被用于缓存、消息队列等多种场景,而Spring框架则为Java开发者提供了强大的依赖注入和面向切面编程功能,使得整合Redis变得轻松便捷。 首先,我们需要在项目中引入Spring ...

    Java自定义注解实现Redis自动缓存的方法

    Java自定义注解实现Redis自动缓存的方法是指在Java应用程序中使用自定义注解来实现Redis自动缓存的功能。该方法可以在实际开发中节省重复劳动,提高开发效率。 首先,需要创建一个自定义注解@RedisCache,该注解将...

    Spring 与Ehcache实现基于方法的缓存

    在IT行业中,Spring框架是Java领域最广泛应用的轻量级框架之一,它为开发者提供了强大的依赖注入(DI)和面向切面编程(AOP)功能。Ehcache则是一款广泛使用的开源缓存解决方案,用于提高应用程序性能,减少数据库...

    springboot实现消息转换、切面AOP和Redis缓存

    在SpringBoot中,你可以使用`@Aspect`注解定义一个切面,`@Before`, `@After`, `@Around`, `@AfterReturning`, `@AfterThrowing`定义不同的通知类型。 下面是一个简单的日志记录切面示例: ```java @Aspect @...

    SpringBoot AOP各种注解、自定义注解、鉴权使用案例(免费下载)

    SpringBoot AOP,即面向切面编程,是Spring框架中的一个重要特性,用于实现代码的横切关注点,如日志记录、事务管理、权限验证等。AOP通过使用代理模式,将这些关注点与核心业务逻辑分离,使得代码更加模块化,更...

    java注解annotation.rar

    5. AOP(面向切面编程):如Spring的`@Aspect`、`@Before`、`@After`等用于定义切面和通知。 总结,Java注解是一种强大的工具,它增强了代码的可读性,简化了配置,并且通过元数据提供了额外的信息层,使得开发过程...

    java项目开发实战--使用ssm框架开发众筹网站.rar

    1. **Spring框架**:Spring是一个开源的应用框架,提供IOC(Inversion of Control)容器来管理对象的生命周期和依赖关系,以及AOP(Aspect-Oriented Programming)用于实现切面编程,增强代码的可维护性和解耦性。...

    深入体验Java+Web开发内幕-高级特性-高清扫描版

    - **Spring框架**:涵盖AOP(面向切面编程)、IoC(控制反转)、事务管理等功能,是Java企业级应用的基石。 - **MyBatis**或Hibernate:持久层框架,简化数据库操作,提供对象关系映射功能。 - **Maven或Gradle**...

    JavaEE spring半自动实现AOP代理

    - 使用`@Aspect`注解来声明一个切面类,切面类中定义了`@Before`、`@After`、`@Around`、`@AfterReturning`和`@AfterThrowing`等通知方法,它们分别代表前置、后置、环绕、返回后和异常后执行的逻辑。 - 使用`@...

    使用spring aop对web 应用数据进行memcached缓存

    - 创建自定义切面,实现缓存逻辑,如使用`@Around`注解编写拦截器。 - 在需要缓存的方法上添加`@Cacheable`等注解。 5. **注意事项**: - 缓存一致性问题:当多个节点同时修改同一数据时,需要确保最终一致性。 ...

    【Java核心知识面试】-阿里Java面试集锦.zip

    - AOP(面向切面编程):讲解切面、通知、代理等概念,以及在Spring中的实现。 9. **数据库** - SQL语言:掌握基本的查询、增删改操作,以及高级特性如索引、事务、存储过程。 - JDBC:了解数据库连接、执行SQL...

    深入体验Java+Web开发内幕-高级特性.pdf 高级的 张孝祥 的第二本好书源码

    - **Spring框架**:提供依赖注入、AOP(面向切面编程)、事务管理等功能,是Java企业级应用的基石。 - **Spring MVC**:Spring的Web MVC模块,用于构建基于HTTP的应用,提供RESTful API设计。 - **Struts2或...

    spring注解方式实现aop

    在Spring中,我们可以通过创建一个类并使用`@Aspect`注解来定义切面。例如: ```java @Aspect public class LoggingAspect { // ... } ``` 2. **编写通知(Advice)** 通知是在特定连接点上执行的代码,例如...

    java web高级编程--英文高清版

    根据提供的文件信息,我们可以推断出这是一本关于Java Web应用程序的专业书籍,作者为Nicholas S. Williams,并由John Wiley & Sons, Inc.出版。本书的全称是《Professional Java® for Web Applications》。虽然...

Global site tag (gtag.js) - Google Analytics