1 扫描包,业务类、切面类都需要
2 需要用注解的时候,需要开启一个aop的注解方式
例:
<?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
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--将业务类、切面类的包扫描,因为要用注解-->
<context:component-scan base-package="com.longteng.lesson2.my.service"/>
<context:component-scan base-package="com.longteng.lesson2.my"/>
<!--开启aop注解方式,此步骤不能少,这样java类中的aop注解才会生效-->
<aop:aspectj-autoproxy/>
</beans>
用springBoot实现aop的话,不用在xml文件里扫描包也不用加下面的这个标签
<aop:aspectj-autoproxy/>
业务类,要用@Service加入到Spring容器中托管,xml文件已经扫描了,业务类有3个方法,增删改
import org.springframework.stereotype.Service;
@Service
public class UserDaoTest {
public String add(String name,Integer age){
return name+age;
}
public String update(String name,Integer age){
return name+age;
}
public String delete(String name,Integer age){
return name+age;
}
}
切面类:切面类加上@Component注解,将该类加入spring容器中托管,xml文件里已经扫描,在切面类加上注解@Aspect,这样就可以使用aop了,切面类中有2个记录时间的方法,在方法上的注解@Before、@After中配入切点(业务类执行哪个方法的时候,进入切面)
@Pointcut(“execution(* com.longteng.lesson2.my.UserDaoTest.(,*))”)
public void pointcut(){} 这个pointcut()方法名也可以是aa(),@Before注解使用的时候value用aa()即可,只要@Pointcut这个确定切点的注解在这个方法上,该方法就可以使用
@Before(value = “pointcut()”)
该 @Before注解也可以是@After、@Around、@AfterReturning…都可以使用,具体用哪个视业务情况而定
这3句话配合使用,不配合使用的话,切点就要写很多遍,
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
@Aspect
public class Halder {
@Pointcut("execution(* com.longteng.lesson2.my.UserDaoTest.*(*,*))")
public void pointcut(){}
@Before(value = "pointcut()")
public void startTime(JoinPoint joinPoint) {
System.out.println(
joinPoint.getTarget().getClass()+"类"+
joinPoint.getSignature().getName()+"方法开始时间" + new Date());
}
@After(value = "execution(* com.longteng.lesson2.my.UserDaoTest.*(*,*))")
public void endTime(JoinPoint joinPoint) {
System.out.println(
joinPoint.getTarget().getClass()+"类"+
joinPoint.getSignature().getName()+"方法结束时间" + new Date());
}
}
@Before、@After的执行结果
@Around环绕通知也是一样的,剩下的在xml实现的文档里copy代码就好
@Pointcut(“execution(* com.longteng.lesson2.my.UserDaoTest.())”)
public void pointcut(){}
@Around(value = “pointcut()”)
@AfterReturning这里只写了切面类Halder,其他的与xml的实现一样,可以copy
@Component
@Aspect
public class Halder {
@AfterReturning
(value = "execution(* com.longteng.lesson2.my.UserDaoTest.AfterReturn(*))",
returning = "keys")
public void doAfterReturningAdvice1(JoinPoint joinPoint, Object keys){
System.out.println(joinPoint.getTarget().getClass()+"类" +
joinPoint.getSignature().getName()+"方法获取到的返回值:"+keys);
}
}
@AfterThrowing这里只写了切面类Halder,其他的与xml的实现一样,可以copy
表达式还是业务类的方法,throwing 是该切面类里要执行切面方法的第二个参数得参数名
@Component
@Aspect
public class Halder {
@AfterThrowing(value = "execution(* com.longteng.lesson2.my.UserDaoTest.*())",throwing = "ex")
public void throwingTest(JoinPoint joinPoint,Throwable ex){
}
}
@DeclareParents
@DeclareParents(value="com.longteng.lesson2.service.Li+",defaultImpl=DoSomething.class)
public Add add;
value=“com.longteng.lesson2.service.Li+”:表示Li类进行增强,也就是Li
中引入一个新的接口;
defaultImpl : 代表其默认的实现类,这里指的是DoSomething
这几个类在xml文件中说明的很清楚了