我有一个bean要向InfluxDB报告。数据库在表中有注册的INFLUX\u DB\u服务器。如果你看一下代码,你会发现方法reportMemory做了很多工作,它构造了一个测量和do调用,当没有InfluxDB时,所有这些工作都是无用的。
所以我们的想法是,如果没有影响数据库,就跳过这项工作。由于公共无效方法不返回值,它对周围的应用程序没有影响。
我能做的是编写一个方法isWorkPossible,并在每次调用时调用该方法。这可能是接吻之后的事,但这违反了干涸。所以我喜欢使用AOP对其进行归档。
但是如果没有注册influxdb,我喜欢跳过所有公共void方法的执行。
/**
* The reporter to notify {@link InfluxDB influxDBs} for changes.
*/
@Named
public class InfluxDBReporter {
/**
* Logger for reporting. For security reasons neither the username nor the
* password should be logged above {@link Level#FINER}.
*/
private static final Logger LOG = Logger.getLogger(InfluxDBReporter.class.getCanonicalName());
/**
* The entitymanager to use, never <code>null</code>.
*/
@PersistenceContext
private final EntityManager entityManager = null;
/**
* The registred {@link InfluxDBServer} in key and the URL in value.
*/
@SkipPublicVoidMethodsIfEmpty
private final Map<InfluxDB, URL> dbs = new LinkedHashMap<>();
/**
* Initializes the connections.
*/
@PostConstruct
private void connect() {
for (InfluxDBServer db : FROM(囗InfluxDBServer.class).all(entityManager)) {
try {
URL dbUrl = new URL(db.getUrl());
InfluxDB idb = InfluxDBFactory.connect(db.getUrl(), db.getUsername(), db.getPassword());
idb.setDatabase(db.getDatabaseName());
dbs.put(idb, dbUrl);
} catch (MalformedURLException e) {
LOG.log(Level.SEVERE, db.getUrl(), e);
}
}
}
/**
* Closes all connections to all {@link InfluxDB}.
*/
@PreDestroy
private void disconnect() {
for (InfluxDB influxDB : dbs.keySet()) {
try {
influxDB.close();
} catch (Exception e) {
// Fault barrier
LOG.log(Level.WARNING, "InfluxDBServer URL: " + dbs.get(idb), e);
}
}
}
/**
* Report memory statistics.
*
* @param availableProcessors Amount of available processors, never negative.
* @param totalMemory The total memory, never negative.
* @param maxMemory The max memory, never negative.
* @param freeMemory The free memory, never negative.
*/
public void reportMemory(int availableProcessors, long totalMemory, long maxMemory, long freeMemory) {
reportAll(Point.measurement("jvm").addField("totalMemory", totalMemory).addField("maxMemory", maxMemory)
.addField("freeMemory", freeMemory));
}
/**
* Report a point to all connected {@link InfluxDBServer}.
*
* @param builder The point to report.
*/
private void reportAll(Builder builder) {
Point infoPoint = builder.time(System.currentTimeMillis(), TimeUnit.MILLISECONDS).build();
for (InfluxDB idb : dbs.keySet()) {
new Thread(() -> {
try {
idb.write(infoPoint);
} catch (Exception e) {
// Fault barrier
LOG.log(Level.WARNING, "InfluxDBServer URL: " + dbs.get(idb), e);
throw e;
}
}).start();
}
}
}
这是我的观点:
@Aspect
public class MethodAnnotations {
@Pointcut("@annotation(xxx.MethodAnnotations.SkipPublicVoidMethodsIfEmpty)")
private void anyOldTransfer(JoinPoint jp) {
System.out.println(jp); <----- never executed.
}
public @interface SkipPublicVoidMethodsIfEmpty {
}
}
我期望系统。出来println在bean被实例化但它没有被实例化时运行。
知道为什么吗?
正如JB Nizet已经说过的那样,@annotation(my.package.MyAnnotation)
旨在捕捉方法上的注释,而不是字段上的注释,这解释了为什么您对那里发生的任何事情的期望都是错误的。
如果你想通过AOP发现一个类是否有一个带有特定注释的成员,你需要使用一个特殊的切入点,比如hasfield(@MyAnnotation**)。但是这个切入点在Spring AOP中不可用,您需要切换到AspectJ。如果您想通过get(@MyAnnotation MyType*)或set(@MyAnnotation MyType*)拦截对此类字段的读/写访问,情况也是如此。
有关更多详细信息,请参阅我的另一个答案。
AspectJ还提供了特殊的切入点
只要时机合适,您可以使用它们来执行方面建议。在您的示例中,如果很明显所有目标类都有一个方法,那么您还可以更容易地连接到PostConstruct方法。
我的回答很笼统,因为你没有详细解释你到底想做什么。因此,请随时提出后续问题。
更新:我查看了你最新的问题更新。我不明白,对于一个非常简单的问题,这是一个非常人为的解决方案,也不是AOP可以解决的好案例。虽然我很喜欢AOP,但我无法理解这种情况是如何成为一个跨领域的问题:
InfluxDBReporter
您使用的注释的唯一目的是告诉一个方面要做什么
更糟糕的是,您将注释放在一个私有字段上,但希望外部类(在本例中是一个方面)对其作出反应。虽然在AspectJ中这在技术上是可能的,但这是一种糟糕的设计,因为您正在将私人信息泄露给外界
通过从示例类中跳过公共方法,您不会保存任何昂贵的与DB相关的操作,因为在空键集上迭代意味着什么也不会发生,因此也不会出现任何与DB相关的错误。这里唯一真正发生的事情是生成器调用。它们应该便宜
即使假设您有更多应该跳过的公共方法,如果您确实想坚持这种方法,我实际上也会这样设计AOP解决方案:
添加一个方法public boolean isConnectedToDB(){return!dbs.isEmpty();}
到应用程序类
在您的方面中,使用一个关于
的建议并从那里调用布尔方法,只调用连接点。如果有任何连接,请继续()。否则,不要继续,而是什么也不做(对于void方法)或返回类似于null的伪结果(对于非void方法)
如果您只有公共void方法或非void方法,则精确解取决于您是只有这一类还是有多个具有类似需求的类。
此外,您提到的是INFLUX\u DB\u服务器,但我不知道这是什么,因为我在您的代码中的任何地方都看不到它。
最后,但并非最不重要的一点:我刚刚注意到,您希望在由切入点注释的方法中发生一些事情。很抱歉,即使切入点没有错,也会发生这种情况,因为切入点定义仅用于实际的通知方法中,例如前后前后左右。您希望执行的操作进入建议,而不是切入点。我建议您在尝试设计基于AOP的解决方案之前,先学习AOP基础知识。
问题内容: 需要一些帮助,我刚刚开始学习Spring,似乎无法弄清楚我们的错: Application.java-没有包 User.java-包com.mapping UserDAO.java-包com.accesors Root.java-包com.controllers 当我运行项目时,我似乎得到了以下启示 堆栈跟踪: 据我了解,这意味着@ComponentScan没有检测到软件包 问题答案:
我正在使用一个Udemy教程学习Spring Boot,它跳过了如何将Spring工具安装到我们的IDE,所以我一直在谷歌自己如何做。 我想把它添加到我现有的Eclipse Jee Oxygen IDE中,因为我在它上面安装了其他的LANG和工具,我想把它全部保存在一个地方。 我试着通过Eclipse中的Marketplace向导搜索它,但它没有出现。 我还尝试了使用Eclipse.com的mar
一面10.11三人一起面 自我介绍,问项目,项目的问题有点怪 怎么给前端传数据 讲分布式锁,下单问题 为什么用b+ linux常用命令 二面10.17问项目三人一起面 自我介绍,说项目,redis怎么解决一人一单问题(我说了分布式锁面试官好像不满意) 为什么选择java,为什么选择我们公司 反问 感受:二面的时候大佬很多,才知道因为它必解决北京户口。感觉国企更喜欢男生…
本文向大家介绍python实现图片横向和纵向拼接,包括了python实现图片横向和纵向拼接的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了python实现图片横向和纵向拼接的具体代码,供大家参考,具体内容如下 直接上代码: 结果: 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。
我在响应式站点上设置了flexSlider。我正在创建的滑块可以拍摄横向和纵向图像。我设置了,以便调整高度以适应图像。 在最大的媒体查询中,flexslider容器的宽度为750px。这对于横向图像很好,但纵向图像太大了。肖像图像的宽度设置为与容器相同的大小-750px宽,因此高度至少是容器宽度的两倍,因此如果不滚动,则无法查看整个图像。 在css中,我尝试设置最大高度:750px,这解决了高度问
我对Guice的理解是: 构造函数级注入()意味着每次通过