)
public void f3(JoinPoint joinPoint) {
Signature signature = joinPoint.getSignature();
System.out.println("切面类f3()-方法执行异常-日志-方法名-" + signature.getName());
}
//最终通知:把 f4方法切入到目标对象方法执行后的位置,无论有无出现异常都会执行
@After(value = "execution(public float com.li.aop.aspectj.SmartDog.getSum(float, float))")
public void f4(JoinPoint joinPoint) {
Signature signature = joinPoint.getSignature();
System.out.println("切面类f4()-方法最终执行完毕-日志-方法名-" + signature.getName());
}
}
2.4配置容器文件beans07.xml:
<?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:context="http://www.springframework.org/schema/context"
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/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--配置自动扫描的包-->
<context:component-scan base-package="com.li.aop.aspectj"/>
<!--一定要开启基于注解的 AOP 功能-->
<aop:aspectj-autoproxy/>
</beans>
2.5测试类:
package com.li.aop.aspectj;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.testng.annotations.Test;
/**
* @author 李
* @version 1.0
* 测试类
*/
public class AopAspectjTest {
@Test
public void smartDogTestByAspectj() {
//得到Spring容器
ApplicationContext ioc =
new ClassPathXmlApplicationContext("beans07.xml");
//通过接口类型来获得注入的SmartDog对象(实际上是代理对象proxy)
SmartAnimal smartAnimal = ioc.getBean(SmartAnimal.class);
//class com.sun.proxy.$Proxy15
//System.out.println("smartAnimal的运行类型=" + smartAnimal.getClass());
smartAnimal.getSum(100, 48);
}
}
测试结果:
6.3细节说明
-
关于切面类方法命名可以自己规范一下
-
切入表达式的更多配置,比如使用模糊配置
形式为:execution(访问修饰符 返回类型 全类名.方法名(形参列表))
@Before(value = "execution(* com.li.aop.aspect.SmartDog.*(..))")
-
下面表示所有访问权限,所有包下所有类的所有方法(前提是基于动态代理的类),都会被执行前置通知方法
@Before(value = "execution(* *.*(..))")
-
spring容器开启了基于注解的AOP功能<aop:aspectj-autoproxy/>
,获取注入的对象则需要以接口的类型来获取,因为你注入的对象.getClass()已经是代理类型了!
-
spring容器开启了基于注解的AOP功能,也可以通过id来获取注入的对象,但也要转成接口类型来获取。
6.4练习
- 有一个接口USBInterface,该接口有一个方法work
- 写出实现子类Phone和Camera
- 写一个切面类,在该切面类中写一个方法(可输出日志信息)等作为前置通知,在Phone和Camera对象执行work方法前调用
- 其他通知,如返回通知,异常通知,后置通知,也可以加入
(1)UsbInterface接口:
package com.li.aop.hw;
/**
* @author 李
* @version 1.0
*/
public interface UsbInterface {
public void work(String s);
}
(2)Phone实现类:
package com.li.aop.hw;
import org.springframework.stereotype.Component;
/**
* @author 李
* @version 1.0
*/
@Component //将Phone对象当做组件注入到容器中
public class Phone implements UsbInterface {
@Override
public void work(String s) {
System.out.println("手机开始工作,参数是=" + s);
}
}
(3)Camera实现类:
package com.li.aop.hw;
import org.springfr