aop是面向切面编程的意思,是相对于面向对象的另一种编程方法,
本文将介绍在spring中使用aspectj基于注解的aop实用开发。
一、关键点
1、aop配置,在xml配置文件中,通过aop:aspectj-autoproxy,加载springAop配置,
特别需要注意其中的属性proxy-target-class和expose-proxy的定义:
a)proxy-target-class,是否使用cglib代理,默认值false
当为false,表示使用jdk动态代理(必须实现接口);
当为true,表示使用cglib代理(直接对类代理,动态生成字节码);
b)expose-proxy,当类中方法相互调用时,是否对后续方法(方法有aop注解)支持aop,默认值false
当为false,不支持,也就是说此时当前类中方法互相调用,除首方法外,后续调用方法即使有aop注解,也不会有aop效果;
当为true,支持,也就是说此时当前类中方法互相调用,当后续调用方法有aop注解,就会有aop效果,
注意,调用方法需要指定当前调用的实例,且写法类似于(MeetService)AopContext.currentProxy()。
2、切面的编写,或者说处理类的编写,类上加@Aspect及@Component注解,接下来是三种处理方式:
a)@Before ,切点前处理,加在处理方法上,同时内加切点参数,即切点的注解,如@Before("@annotation(hello)");
b)@Round ,切点前后处理,加在处理方法上,同时内加切点参数,即切点的注解;
c)@After ,切点后处理,加在处理方法上,同时内加切点参数,即切点的注解;
另外,从方法参数JoinPoint(before或after)和ProceedingJoinPoint(around)获取切点的方法签名,从而获取切点方法各种信息;
从注解参数可以获取aop注解传递的信息。
二、实例
1、添加maven依赖
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>4.3.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.3.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>4.3.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>4.3.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-asm</artifactId> <version>3.1.4.RELEASE</version> </dependency> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.2.4</version> </dependency>2、添加spring配置spring-aop.xml
<aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true" />3、定义aop注解
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Hello { String helloStyle() default ""; }4、定义aop注解操作
@Aspect @Component public class HelloHandler { /** * 切点前操作 * @param joinPoint * @param hello */ @Before("@annotation(hello)") public void beforeHello(JoinPoint joinPoint,Hello hello){ MethodSignature signature = (MethodSignature) joinPoint.getSignature(); //获取注解对应方法的方法签名 Method method = signature.getMethod(); //获取注解对应的方法 System.out.println("beforeHello method name : "+ method.getName()+" helloStyle : "+ hello.helloStyle()); } /** * 切点前后操作 * @param pjp * @param hello * @return * @throws Throwable */ @Around("@annotation(hello)") public Object aroundHello(ProceedingJoinPoint pjp , Hello hello) throws Throwable { String result = (String) pjp.proceed(); //执行方法,并获取方法返回结果 System.out.println("aroundHello result is :"+result); result = hello.helloStyle() + " , "+ result; //加工处理方法结果 return result; } /** * 切点后操作 * @param joinPoint * @param hello */ @After("@annotation(hello)") public void afterHello(JoinPoint joinPoint,Hello hello){ MethodSignature signature = (MethodSignature)joinPoint.getSignature(); Method method = signature.getMethod(); System.out.println("afterHello method name : "+ method.getName()+" helloStyle : "+ hello.helloStyle()); } }5、定义服务接口
public interface MeetService { String meet(String name); String meet1(String name); }6、定义服务实例
@Service("meetService") public class MeetServiceImpl implements MeetService { @Hello(helloStyle = "hi") public String meet(String name){ return name; } public String meet1(String name){ try{ MeetService meetService = (MeetService)AopContext.currentProxy(); //获取当前类的代理实例 String result = meetService.meet(name)+1; //调用当前类方法 return result; }catch (Exception e){ } return meet(name); } }7、测试
public class SpringAopMain { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-config.xml"); MeetService meetService = context.getBean(MeetService.class); String result = meetService.meet("apple"); //调用有aop注解的方法 System.out.println("main invoke meet result : "+result); System.out.println("---------------------------------------------------------------"); result = meetService.meet1("banana"); //调用方法(可以有aop注解),同时方法内又调用了当前类方法且含有aop注解 System.out.println("main invoke meet result : "+result); } }运行结果:
beforeHello method name : meet helloStyle : hi
aroundHello result is :apple
afterHello method name : meet helloStyle : hi
main invoke meet result : hi , apple
---------------------------------------------------------------
beforeHello method name : meet helloStyle : hi
aroundHello result is :banana
afterHello method name : meet helloStyle : hi
main invoke meet result : hi , banana1