1.定义:AOP:Aspect Oriented Programming 面向切面编程; 在运行时动态的将代码切入到指定的点,方法位置上,可以随意添加和删除,不对源代码产生影响,具有解耦的作用;
2.主要作用:方法执行前,执行后需要记录日志,或者执行前需要验证操作权限之类的可以动态的切入,而不用重复的去实现,
3.Aspect 中使用到的注解:
Join Point:表示在程序中明确定义的执行点,典型的Join point包括方法调用,对类成员的访问以及异常处理程序块的执行,他自身还可以嵌套其他Join Point;
PointCut:事件切入点:表示一组Join Point,把事件发生的地点进行了规律性的总结,通过通配,正则表达式等方式集中起来,定义了相应的advice(事件)要发生的地方;正则表达式 (com.example.service.*,即所有在 service 包下面的方法);
Advice:advice定义了在Point Cut里面定义的程序点具体要做的操作,他通过@before,@after 和@around 来区别是在每个join Point 之前,之后还是代替执行的代码;
4.Aop中所用的表达式
其中 execution 是用的最多的,其格式为:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?)
returning type pattern,name pattern, and parameters pattern是必须的.
ret-type-pattern:可以为*表示任何返回值,全路径的类名等.
name-pattern:指定方法名,*代表所以,set*,代表以set开头的所有方法.
parameters pattern:指定方法参数(声明的类型),(..)代表所有参数,(*)代表一个参数,(*,String)代表第一个参数为任何值,第二个为String类型.
(1)定义在service包里的任意方法的执行:execution(* com.zhou.service.*.*(..))
(2)定义在service包和所有子包里的任意类的任意方法的执行:execution(* com.zhou.service..*.*(..))
(3)AccountService 接口的任意方法的执行:execution(* com.zhou.service.AccountService.*(..))
5.简单的demo,方法之前执行before:
需要引入的包:
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.8.10</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.10</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjtools</artifactId> <version>1.8.10</version> </dependency> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-aop --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>4.3.11.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.10.RELEASE</version> </dependency>
在spring xml中需要配置:
<aop:aspectj-autoproxy/> <context:component-scan base-package="com.zhou"/>
定义简单的注解:
@Retention(RetentionPolicy.RUNTIME) public @interface LogAnnotation { public String description() default "init"; }
注解切入点:有两种方式,一种是直接在代码中写,另一种就是在xml中配置;
@Aspect public class LogIntecept { public void logPoint(){ } @Before(value = "execution(* com.zhou.module..*.*(..))") public void methodBeforeLog(){ System.out.println("method BeforeLog()"); } }
或者是这样:
<!--<aop:config> <aop:aspect id="myLogAspect" ref="logIntecept"> <aop:pointcut id="logPointCut" expression="execution(* com.zhou.module..*.*(..))"/> <aop:before method="methodBeforeLog" pointcut-ref="logPointCut"/> </aop:aspect> </aop:config>-->
在接口中引入 @Annotation
import com.zhou.annotation.LogAnnotation; public interface TaskBO { @LogAnnotation(description = "recieveTask") public void recieveTask(); }
public class TaskBOImpl implements TaskBO { public void recieveTask() { System.out.println("do something()"); } }
以上基本上级就是简单的aop 代码:
在main中测试下:
/** * Hello world! * */ public class App { public static void main( String[] args ) { System.out.println( "Hello World!" ); ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml"); TaskBO taskBO = (TaskBO) context.getBean("taskBO"); taskBO.recieveTask(); } }
输出: