31--基于@AspectJ的AOP

版权声明:如有转载,请标明出处,谢谢合作! https://blog.csdn.net/lyc_liyanchao/article/details/83753308

上一节介绍了基于Schema的AOP,本篇介绍基于@AspectJ的AOP。

1.@AspectJ切面
  • 目标对象
package com.lyc.cn.v2.day07;

public interface Animal {
	void sayHello();
}
package com.lyc.cn.v2.day07;

public class Dog implements Animal {
	public void sayHello() {
		System.out.println("--被增强的方法");
	}
}
  • 引介
package com.lyc.cn.v2.day07;

public interface IIntroduce {
	void sayIntroduce();
}
package com.lyc.cn.v2.day07;

public class IntroduceImpl implements IIntroduce {
	@Override
	public void sayIntroduce() {
		System.out.println("--引入");
	}
}
  • 切面
package com.lyc.cn.v2.day07;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;

/**
 * 切面类
 * @author: LiYanChao
 * @create: 2018-10-31 15:46
 */
@Aspect
public class DogAspect {

	/**
	 * 例如:execution (* com.sample.service.impl..*.*(..)
	 * 1、execution(): 表达式主体。
	 * 2、第一个*号:表示返回类型,*号表示所有的类型。
	 * 3、包名:表示需要拦截的包名,后面的两个点表示当前包和当前包的所有子包,
	 * 即com.sample.service.impl包、子孙包下所有类的方法。
	 * 4、第二个*号:表示类名,*号表示所有的类。
	 * 5、*(..):最后这个星号表示方法名,*号表示所有的方法,后面括弧里面表示方法的参数,两个点表示任何参数。
	 **/
	@Pointcut("execution(* com.lyc.cn.v2.day07.*.*(..))")
	public void test() {

	}

	@Before("test()")
	public void beforeTest() {
		System.out.println("==前置增强");
	}

	@After("test()")
	public void afterTest() {
		System.out.println("==后置最终增强");
	}

	@AfterThrowing("test()")
	public void afterThrowingTest() {
		System.out.println("==后置异常增强");
	}

	@AfterReturning("test()")
	public void afterReturningTest() {
		System.out.println("==后置返回增强");
	}

	@Around("test()")
	public Object aroundTest(ProceedingJoinPoint p) {
		System.out.println("==环绕增强开始");
		Object o = null;
		try {
			o = p.proceed();
		} catch (Throwable e) {
			e.printStackTrace();
		}
		System.out.println("==环绕增强结束");
		return o;
	}

	@DeclareParents(value = "com.lyc.cn.v2.day07.Dog", defaultImpl = IntroduceImpl.class)
	private IIntroduce iIntroduce;


}
  • 配置文件
<?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">

	<!--
        1、proxy-target-class
            如果被代理的目标对象至少实现了一个接口,则会使用JDK动态代理,所有实现该目标类实现的接口都将被代理
            如果该目标对象没有实现任何接口,则创建CGLIB动态代理。
            但是可以通过proxy-target-class属性强制指定使用CGLIB代理,
        2、expose-proxy
            解决目标对象内部的自我调用无法实施切面增强的问题
    -->
	<aop:aspectj-autoproxy proxy-target-class="true">
		<!-- 指定@Aspect类,支持正则表达式,符合该表达式的切面类才会被应用-->
		<aop:include name="dogAspect"></aop:include>
	</aop:aspectj-autoproxy>

	<!--bean-->
	<bean id="dog" class="com.lyc.cn.v2.day07.Dog"/>

	<!--AspectJ-->
	<bean name="dogAspect" class="com.lyc.cn.v2.day07.DogAspect"/>

</beans>
  • 测试及结果
package com.lyc.cn.v2.day07;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {

	@Test
	public void test1() {
		// 基于@AspectJ注解方式
		ApplicationContext ctx = new ClassPathXmlApplicationContext("v2/day07.xml");
		Dog dog = ctx.getBean("dog", Dog.class);
		dog.sayHello();
	}


	@Test
	public void test2() {
		// 引入
		ApplicationContext ctx = new ClassPathXmlApplicationContext("v2/day07.xml");
		// 注意:getBean获取的是dog
		IIntroduce introduce = ctx.getBean("dog", IIntroduce.class);
		introduce.sayIntroduce();
	}

}
// 测试一
==环绕增强开始
==前置增强
--被增强的方法
==环绕增强结束
==后置最终增强
==后置返回增强
// 测试二
--引入
2.总结

前篇和本篇主要还是回顾了SpringAop的使用方式,也为了接下来的源码分析做好测试类准备,在接下来的分析中主要讲解以@AspectJ方式的实现方式。

猜你喜欢

转载自blog.csdn.net/lyc_liyanchao/article/details/83753308