一、自定义注解
@Interface自动继承了java.lang.annotation.Annotation接口进行自定义注解,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。
定义注解格式:
public @interface 注解名 {定义体}
@Target:
表示该注解可以用于什么地方,可能的ElementType参数有: CONSTRUCTOR
:构造器的声明 FIELD
:域声明(包括enum
实例) LOCAL_VARIABLE
:局部变量声明 METHOD
:方法声明 PACKAGE
:包声明 PARAMETER
:参数声明 TYPE
:类、接口(包括注解类型)或enum
声明
@Retention:
表示需要在什么级别保存该注解信息。可选的RetentionPolicy参数包括: SOURCE
:注解将被编译器丢弃 CLASS
:注解在class文件中可用,但会被VM丢弃 RUNTIME
:VM将在运行期间保留注解,因此可以通过反射机制读取注解的信息
@Document:
将注解包含在Javadoc中
@Inherited:
允许子类继承父类中的注解
实例
自定义注解范围为类
package zidingyi; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Table { String value() default ""; }
自定义注解范围为域
package zidingyi; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import jdk.internal.instrumentation.TypeMapping; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Colum { String value() default ""; }
使用自定义注解
package zidingyi; @Table("user") public class User { @Colum("_id") private String id; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Colum("name") private String name; }
二、使用@AspectJ
1、Aspect简单使用
创建目标类
package aspectj; public class WaiterNew { public void greetTo(String clientName){ System.out.println("greet To:"+clientName); } public void serverTo(String clientName){ System.out.println("serverTo:"+clientName); } }
创建切面类
package aspectj; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; //通过@Aspectj注解将该类标示为切面 @Aspect public class GreetToAspect { //定义增强和切点 @Before("execution(* aspectj.WaiterNew.greetTo(..))") public void beforeGreeting(){//该部分为增强的逻辑 System.out.println("How Are You"); } }
测试
package aspectj; import org.aspectj.lang.annotation.Aspect; import org.springframework.aop.aspectj.AspectInstanceFactory; import org.springframework.aop.aspectj.annotation.AspectJProxyFactory; public class AspectJTest { public static void main(String[] args){ WaiterNew waiterNew = new WaiterNew(); AspectJProxyFactory factory = new AspectJProxyFactory(); factory.setTarget(waiterNew); factory.addAspect(GreetToAspect.class); WaiterNew waiterNew2 = factory.getProxy(); waiterNew2.greetTo("abc"); waiterNew2.serverTo("bcd"); } }
切点语法
@Aspect是一种定义切面的注解。
@Before是一种前置增强的注解,相当于MethodBeforeAdvice类。
@AfterReturning是一种后置增强的注解,相当于AfterReturningAdvice类。
@Around是一种环绕增强注解,相当于MethodInterceptor类。
@AfterThrowing是一种异常抛出增强注解,相当于ThrowsAdvice类。
复合切点
复合切点是多个节点的组合,复合切点通过逻辑运算符进行组合,逻辑运算符如下:
&&:表示多个切点的交集。
||:表示多个切点的并集。
!:相当于切点的反集运算。
切点函数
方法切点函数
通过描述目标类方法定义连接点
execution():表示匹配所有该目标类方法的连接点
@annotation:表示标注了特定注解的目标类方法作为连接点。
方法入参函数
args():表示目标类方法入参时的对象类型指定连接点。
@args():表示入参对象是否标注指定注解指定连接点。
目标类切点函数
target():与指定类名相符的目标类中的所有函数作为连接点。
@target():将标注指定注解的类中的所有函数作为连接点。
within():与指定类名相符的目标类中的所有函数作为连接点。
@within():将标注指定注解的类中的所有函数作为连接点。