java注解与基于@AspectJ的AOP

1 注解

1.1 要点

元注解:注解的注解
@Retention(生命范围:源代码,class,runtime)、@Inherited、@Documented、@Target(作用范围,方法,属性,构造方法等)。

 @Target 表示该注解用于什么地方,可能的值在枚举类 ElemenetType 中,包括: 
      ElemenetType.CONSTRUCTOR----------------------------构造器声明 
      ElemenetType.FIELD --------------------------------------域声明(包括 enum 实例) 
      ElemenetType.LOCAL_VARIABLE------------------------- 局部变量声明 
      ElemenetType.METHOD ----------------------------------方法声明 
      ElemenetType.PACKAGE --------------------------------- 包声明 
      ElemenetType.PARAMETER ------------------------------参数声明 
      ElemenetType.TYPE--------------------------------------- 类,接口(包括注解类型)或enum声明    
 @Retention 表示在什么级别保存该注解信息。可选的参数值在枚举类型 RetentionPolicy 中,包括: 
      RetentionPolicy.SOURCE ---------------------------------注解将被编译器丢弃 
      RetentionPolicy.CLASS -----------------------------------注解在class文件中可用,但会被VM丢弃 
      RetentionPolicy.RUNTIME VM-------将在运行期也保留注释,因此可以通过反射机制读取注解的信息。           
  @Documented 将此注解包含在 javadoc 中 ,它代表着此注解会被javadoc工具提取成文档。在doc文档中的内容会因为此注解的信息内容不同而不同。相当与@see,@param 等。 

  @Inherited 允许子类继承父类中的注解。

1.2 使用

自定义注解

@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Description {
    String desc();
    String author();
    int age() default 18;
}

String desc();虽然它很类似于接口里面的方法,其实它在注解里面只是一个成员变量(成员以无参无异常的方式声明),int age() default 18;(成员变量可以用default指定一个默认值的)

①.成员类型是受限制的,合法的类型包括基本的数据类型以及String,Class,Annotation,Enumeration等。
②.如果注解只有一个成员,则成员名必须取名为value(),在使用时可以忽略成员名和赋值号(=)。
③.注解类可以没有成员,没有成员的注解称为标识注解。

使用自定义注解
@<注解名>(<成员名1>=<成员值1>,<成员名1>=<成员值1>,…)

@Description(desc="i am Color",author="boy",age=18)
public String Color() {
    return "red";
}

解析注解

public class ParseAnn {
    public static void main(String[] args) {
        try {
            // 使用类加载器加载类
            Class c = Class.forName("com.test.Child");

            // 类上面的注解
            boolean isExist = c.isAnnotationPresent(Description.class);
            // 上面的这个方法是用这个类来判断这个类是否存在Description这样的一个注解
            if (isExist) {
                // 拿到注解实例,解析类上面的注解
                Description d = (Description) c.getAnnotation(Description.class);
                System.out.println(d.value());
            }

            //方法上的注解
            //获取所有的方法
            Method[] ms = c.getMethods();
            // 遍历所有的方法
            for (Method m : ms) {
                boolean isExist1 = m.isAnnotationPresent(Description.class);
                if (isExist1) {
                    Description d1=m.getAnnotation(Description.class);
                    System.out.println(d1.value());
                }
            }

            //另一种解析方法
            for (Method m : ms) {
                //拿到方法上的所有的注解
                Annotation[] as=m.getAnnotations();
                for (Annotation a : as) {
                    //用二元操作符判断a是否是Description的实例
                    if (a instanceof Description) {
                        Description d=(Description) a;
                        System.out.println(d.value());
                    }
                }
            }

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

基于@AspectJ的AOP

定义一个将使用切面的类:

public class NaiveWaiter implements Waiter {
    @Override
    public void greetTo(String clientName) {
        System.out.println("greeting to "+ clientName +"...");
    }

    @Override
    public void serveTo(String clientName) {
        System.out.println("serving to "+ clientName +"...");
    }
}

使用@AspectJ定义一个切面

@Aspect
public class PreGreetingAspect {

    @Before("execution(* greetTo(..))")
    public void beforeGreeting(){
        System.out.println("how are you");
    }

//带参数的增强方法
    /*@Before("execution(* greetTo(..))&&args(name)")
    public void beforeGreeting(JoinPoint jp,String name){
        System.out.println("how are you   "+jp.getArgs()[0]);
        System.out.println("how are you   "+name);
    }*/

//使用命名切点   
    /*@After("com.smart.aspect.pointcut.TestNamePointcut.serveToPointcut()")
    public  void afterServing(){
        System.out.println("Bye");
    }*/

}

在spring配置文件中配置使用@AspectJ切面

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="waiter" class="com.smart.NaiveWaiter"/>
    <bean class="com.smart.aspect.aspect.PreGreetingAspect"/>
     <!--<bean class="com.smart.aspect.aspect.AfterServingAspect"/>-->
    <aop:aspectj-autoproxy/>
</beans>

测试类:

package com.smart.aspect.example;

import com.smart.Waiter;
import com.smart.aspect.aspect.PreGreetingAspect;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.aop.aspectj.annotation.AspectJProxyFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath*:spring-config.xml")
public class AspectJProxyTest {

    @Autowired(required = true)
    private Waiter waiter;

    @Test
    public void test() {
        // ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath*:spring-config.xml");
        // Waiter waiter = (Waiter) ctx.getBean("waiter");
        waiter.greetTo("mary");
      //  waiter.serveTo("mary");
    }


    /*public static void main(String[] args) {

        Waiter target = new NaiveWaiter();
        AspectJProxyFactory factory = new AspectJProxyFactory();
        factory.setTarget(target);
        factory.addAspect(PreGreetingAspect.class);

        Waiter proxy = factory.getProxy();

        proxy.greetTo("john");
        proxy.serveTo("john");
    }*/
}

运行结果:
这里写图片描述

注解部分参考:https://www.jianshu.com/p/b560b30726d4

猜你喜欢

转载自blog.csdn.net/my_wings/article/details/82018203