一、自定义注解
@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():将标注指定注解的类中的所有函数作为连接点。