导入依赖包
spring-aop,spring-context,spring-aspects,spring-test,junit
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
编写配置类和切面类(这里我放一起)
@Aspect//注册切面
@Configuration//注册配置类
@EnableAspectJAutoProxy//开启AOP
@ComponentScan("com.xiehetao")//注册扫描包
public class SpringAop {
@Pointcut("execution(* com.xiehetao.*.*(..))")
public void pj(){}
@Before("pj()")
public void sayHi(){
System.out.println("2");
}
@After("pj()")
public void sayHello(){
System.out.println("5");
}
@AfterReturning("pj()")
public void sayGood(){
System.out.println("6");
}
@AfterThrowing("pj()")
public void sayNo(){
System.out.println("6");
}
@Around("pj()")
//这里需要注意,返回的参数类型要与被加强方法的参数一致,否则会报错
public int process(ProceedingJoinPoint joinPoint){
System.out.println("1");
int obj=0;
try{
obj = (Integer)joinPoint.proceed();
System.out.println("4");
}catch (Throwable e){
return 7;
}
return obj;
}
}
被加强类
@Component
public class Girl /*implement Student*/{//实现了接口,java会用JDK动态代理,可以设置成cglib的方式来处理
public int dance(){
System.out.println("3");
int i=1/0;//这里注释掉就是正常返回
return 7;
}
}
interface Student {
int dance();
}
测试类
@RunWith(SpringJUnit4ClassRunner.class)//junit整合spring
@ContextConfiguration(classes={SpringAop.class})//标出配置类,如果是配置文件,使用locations参数
public class test {
@Autowired
private Girl girl;
//private Student girl;//如果是jdk动态代理,这里必须是接口类型,如果用上面的注入方式,会报错
@Test
public void Test(){
System.out.println(girl.dance());
// System.out.println(ans);
}
}
总结:
纯注解方式开发AOP步骤:
1.添加依赖包
spring-aop,spring-context,spring-aspects,spring-test,junit(后俩用于单元测试)
2.标记注解类(相当于xml文件),添加扫描包路径,添加切面,添加AOP动态代理(有两种代理方式,一种是JDK动态代理,通过实现接口的方式,一种是CGlib,通过类的方式来实现,但这种不能增强final类)
3.编写advice(通知)
通知有五种,前置,后置,返回后置,异常通知,环绕通知
通知的执行顺序已经在类中用数字标出来了
优先环绕通知,然后后置通知在返回后置和异常通知之前
建议使用环绕通知
4.关于JDK动态代理和cglib动态代理,测试了下
如果希望用JDK动态代理的方式实现,就定义一个接口,然后实现该接口,在测试时,注入的对象必须是接口类型(实现类的方式注入,会报错,@Autowired查找是按类型查找的,girl有两个类型,一个是接口类型,一个是实体类型)
报错类型:
Error creating bean with name ‘com.xiehetao.test’: Unsatisfied dependency expressed through field ‘girl’;
nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named ‘girl’ is expected to be of type ‘com.xiehetao.Girl’ but was actually of type 'com.sun.proxy.$Proxy29’
如果希望用cglib动态代理的方式实现,直接实现类就可以
这里java是自动判断的,看那种方式合适,默认方式是JDK动态代理