1 /* 2 * Copyright (c) 2012-2024, jcabi.com 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 1) Redistributions of source code must retain the above 8 * copyright notice, this list of conditions and the following 9 * disclaimer. 2) Redistributions in binary form must reproduce the above 10 * copyright notice, this list of conditions and the following 11 * disclaimer in the documentation and/or other materials provided 12 * with the distribution. 3) Neither the name of the jcabi.com nor 13 * the names of its contributors may be used to endorse or promote 14 * products derived from this software without specific prior written 15 * permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 19 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 28 * OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 package com.jcabi.aspects; 31 32 import java.lang.annotation.Documented; 33 import java.lang.annotation.ElementType; 34 import java.lang.annotation.Retention; 35 import java.lang.annotation.RetentionPolicy; 36 import java.lang.annotation.Target; 37 import java.util.concurrent.TimeUnit; 38 39 /** 40 * Makes a method response cacheable in memory for some time. 41 * 42 * <p>For example, this {@code load()} method loads some data from the network 43 * and we want it to cache loaded data for 5 seconds (to avoid delays): 44 * 45 * <pre> @Cacheable(lifetime = 5, unit = TimeUnit.SECONDS) 46 * String load(String resource) throws IOException { 47 * return "something"; 48 * }</pre> 49 * 50 * <p>You can cache them forever, which means that once calculated and 51 * cached value will never expire (may be a nice alternative to static 52 * initializers): 53 * 54 * <pre> @Cacheable(forever = true) 55 * String load(String resource) throws IOException { 56 * return "something"; 57 * }</pre> 58 * 59 * <p>Since version 0.7.14 you can also annotate methods that should flush 60 * cache of the object. 61 * 62 * <p>Since 0.7.18 you can control when exactly flushing happens, with 63 * {@link Cacheable.FlushBefore} and {@link Cacheable.FlushAfter} annotations 64 * ({@link Cacheable.Flush} is deprecated), for example: 65 * 66 * <pre>public class Page { 67 * @Cacheable 68 * public String get() { 69 * // load data from external source, e.g. the network 70 * return data; 71 * } 72 * @Cacheable.FlushBefore 73 * public void set(String data) { 74 * // save data to the network 75 * } 76 * }</pre> 77 * 78 * @since 0.7.7 79 * @see <a href="http://aspects.jcabi.com">http://aspects.jcabi.com/</a> 80 */ 81 @Documented 82 @Retention(RetentionPolicy.RUNTIME) 83 @Target(ElementType.METHOD) 84 public @interface Cacheable { 85 86 /** 87 * Lifetime of an object in cache, in time units. 88 * @return The time amount 89 */ 90 int lifetime() default 1; 91 92 /** 93 * Time units of object lifetime. 94 * 95 * <p>The minimum unit you can use is a second. We simply can't cache for 96 * less than a second, because cache is being cleaned every second. 97 * @return The time unit 98 */ 99 TimeUnit unit() default TimeUnit.MINUTES; 100 101 /** 102 * Keep in cache forever. 103 * @return The flag 104 */ 105 boolean forever() default false; 106 107 /** 108 * Returns the current store after the expiration, and 109 * then asynchronously update the data. 110 * @return The flag 111 */ 112 boolean asyncUpdate() default false; 113 114 /** 115 * Before-flushing trigger(s). 116 * 117 * <p>Before calling the method, call static method {@code flushBefore()} 118 * in this class and, according to its result, either flush or not. 119 * For example: 120 * 121 * <pre> class Foo { 122 * @Cacheable(before = Foo.class) 123 * int read() { 124 * // return some number 125 * } 126 * public static boolean flushBefore() { 127 * // if TRUE is returned, flushing will happen before 128 * // the call to #read() 129 * } 130 * }</pre> 131 * 132 * @since 0.21 133 * @return The array of types 134 */ 135 Class<?>[] before() default { }; 136 137 /** 138 * After-flushing trigger(s). 139 * 140 * <p>After calling the method, call static method {@code flushAfter()} 141 * in this class and, according to its result, either flush or not. 142 * For example: 143 * 144 * <pre> class Foo { 145 * @Cacheable(after = Foo.class) 146 * int read() { 147 * // return some number 148 * } 149 * public static boolean flushAfter() { 150 * // if TRUE is returned, flushing will happen after 151 * // the call to #read() 152 * } 153 * }</pre> 154 * 155 * @since 0.21 156 * @return The array of types 157 */ 158 Class<?>[] after() default { }; 159 160 /** 161 * Identifies a method that should flush all cached entities of 162 * this class/object. 163 * @since 0.7.14 164 * @deprecated It is identical to {@link Cacheable.FlushBefore} 165 */ 166 @Documented 167 @Retention(RetentionPolicy.RUNTIME) 168 @Target(ElementType.METHOD) 169 @Deprecated 170 @interface Flush { 171 } 172 173 /** 174 * Identifies a method that should flush all cached entities of 175 * this class/object, before being executed. 176 * @since 0.7.18 177 */ 178 @Documented 179 @Retention(RetentionPolicy.RUNTIME) 180 @Target(ElementType.METHOD) 181 @interface FlushBefore { 182 } 183 184 /** 185 * Identifies a method that should flush all cached entities of 186 * this class/object, after being executed. 187 * @since 0.7.18 188 */ 189 @Documented 190 @Retention(RetentionPolicy.RUNTIME) 191 @Target(ElementType.METHOD) 192 @interface FlushAfter { 193 } 194 195 }