您的位置:首页 > 编程语言 > Java开发

[002]一步一步学懂spring - AOP和自定义注解

2017-07-18 09:14 267 查看
     Spring有两大核心功能,一个是IOC,一个是AOP。IOC对于开发者来讲可能用的还比较多,声明一个bean交给spring容器来管理,或者从spring容器中找到某个bean注入到某一个bean中。而对于AOP来讲,普通开发者用的就不是很多了。往往是项目的整体架构都已经对切面进行处理完毕了,记录日志也好,处理数据库事务也好等等这些功能,程序员一般是不需要关注的,当然这也是AOP的核心--关注点分离。这篇笔记并不是来记录如何使用AOP的,对于AOP的讲解网络上有很多的文章,可以参考。这里主要介绍的是使用spring的Java配置的方式实现AOP,以及使用自定义注解。
     用一个实际的例子来演示使用注解和使用单纯的AOP的方式来面向切面编程。我们这里需要一个注解类,两个服务提供者,一个切面,再加一个配置类和一个运行的类,运行的类并充当服务的消费者。
注解类
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Action {

String name();

}

这里定义了一个注解,表示是运行时生效,目标是标注在方法上。可以指定一个name属性。注解本身就是一个标记,是没有任何的功能的。

第一个服务的提供者,不使用注解  

@Service
public class DemoService {

public void add() {

}

}

这里就提供了一个空的add方法

第二个服务的提供者,使用注解
@Service
public class DemoAnnotationService {

@Action(name="注解拦截的add操作")
public void add() {

}

}

这里和第一个服务的提供者类似,同样提供了一个空的add方法,只是在add方法上标注了我们定义的action注解,并指定了name属性的值
切面
@Aspect
@Component
public class LogAspect {

@Pointcut("@annotation(com.hy.spring.test3.Action)")
public void annotationPointCut() {}

@Before("execution(* com.hy.spring.test3.DemoService.*(..))")
public void begin(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();

System.out.println("方法规则式拦截 " + method.getName());
}

@After("annotationPointCut()")
public void after (JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();

Method method = signature.getMethod();
Action action = method.getAnnotation(Action.class);
System.out.println("注解式拦截 " + action.name());
}

}

这个是我们的核心代码,先看注解,这里用到了Aspect,Component,Pointcut,Before,After。分别介绍这5个注解

Aspect
声明一个切面
Pointcut
声明切点
Before
声明前置通知
After
声明后置通知
Component
交给spring容器来管理
了解了注解的基本功能之后,再来对代码进行分析。如果对AOP不熟悉的小伙伴可以先了解一下AOP的相关内容,再来继续向下看。这里其实就是两个通知,一个前置通知,一个后置通知,分别对应这两个切入点。切入点的配置方式有两种,第一种就是在前置通知中定义的形式,直接将切面表达式写到注解中,另外可以单独将切入点定义处理,并使用Pointcut来声明这个切入点表达式,方法的名字就是切点的名称。后置通知中就是使用的这种形式,在后置通知的注解中指定切点的方法名,这里一定要把方法的()加上,否则找不到切点。切点表达式定义的都非常简单,annotationPointCut()切点就是要切带有com.hy.spring.test3.Action这个注解的所有类, @Before("execution(*
com.hy.spring.test3.DemoService.*(..))")要切的就是com.hy.spring.test3.DemoService这个包下的所有类。下面我们再来看切了之后干的啥事,不难发现,做的事情也是非常的简单,带有注解的就是打印了注解中配置的值,没有注解的就打印了方法的名字。

配置类
@Configuration
@ComponentScan(value= "com.hy.spring.test3")
@EnableAspectJAutoProxy
public class AopConfig {

}

ComponentScan是要扫描的包,这个注解会自动扫描指定包下的所有的类
EnableAspectJAutoProxy是开启切面的自动代理

测试类
public class Main {

public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AopConfig.class);

DemoAnnotationService service = context.getBean(DemoAnnotationService.class);
service.add();

context.close();
}

}

这里只演示了注解的切面,非注解的同样。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java spring aop 注解 切面