package money.demo;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
/**
* @Author lyr
* @create 2020/1/6 22:49
*/
@Aspect
public class AspectDemo {
@Before(value = "execution(* money.dao.impl.DaoImpl.*(..))")
public void beforeAdvice()
{
System.out.println("start");
}
}
package money.dao.impl;
import money.dao.Dao;
import money.pojo.Person;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.springframework.stereotype.Repository;
import javax.annotation.Resource;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;
/**
* @Author lyr
* @create 2019/12/18 0:19
*/
@Repository("daoImpl")
public class DaoImpl implements Dao {
public void setRunner(QueryRunner runner) {
this.runner = runner;
}
@Resource
private QueryRunner runner;
private BeanListHandler<Person> handler = new BeanListHandler<>(Person.class);
@Override
public void save() {
System.out.println("数据保存到数据库中了");
}
@Override
public List<Person> findAll() {
try {
return runner.query("select * from Person",handler);
} catch (SQLException e) {
e.printStackTrace();
}
return new LinkedList<>();
}
}
在 bean.xml 中添加切面类即可
运行下面代码:
import money.dao.Dao;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
import java.util.HashMap;
/**
* @Author lyr
* @create 2019/12/18 12:41
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:bean.xml")
public class Test {
@Resource(name = "daoImpl")
private Dao daoImpl;
@org.junit.Test
public void print()
{
daoImpl.save();
}
}
总结一下几大通知
@Before 前置通知(beforeAdvice)
@AfterReturning 后置通知,相当于AfterReturningAdvice
@Around 环绕通知,就是集合了 前置和 后置两种通知
@After 最终通知,不管有没有异常,都会执行
@AfterThrowing 抛出异常时的通知 ,即 ThrowAdvice
如果多个通知使用同一个切点,这样就不方便维护,有一个地方要改,那么多个地方都要改,因此,可以使用一个空方法配置切点名称
如下:
package money.demo;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
/**
* @Author lyr
* @create 2020/1/6 22:49
*/
@Aspect
public class AspectDemo {
@Before(value = "execution(* money.dao.impl.DaoImpl.*(..))")
public void beforeAdvice(JoinPoint joinPoint)
{
System.out.println(joinPoint);
System.out.println("start");
}
@AfterReturning(value = "findAllPointcut()",returning = "result")
public void afterReturn(JoinPoint joinPoint,Object result)
{
System.out.println(joinPoint+" -> "+result);
}
@Around("findAllPointcut()")
public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("方法执行前拦截");
Object res = joinPoint.proceed();
System.out.println("环绕后通知");
return res;
}
// 切点命名方法
@Pointcut("execution(* money.dao.impl.DaoImpl.findAll(..))")
public void findAllPointcut(){}
}
同理:下面是基于 xml 配置的切入点
<!-- 开启aop -->
<aop:aspectj-autoproxy/>
<!-- 定义切面目标类 -->
<bean class="money.demo.AspectDemo"/>
<!-- aop配置 -->
<aop:config>
<aop:pointcut id="findAll" expression="execution(* money.dao.impl.DaoImpl.findAll(..))"/>
<aop:aspect ref="aspectDemo">
<aop:after-throwing method="exceptionHandler" throwing="e" pointcut-ref="findAll"/>
<aop:around method="aroundAdvice" pointcut-ref="findAll"/>
</aop:aspect>
</aop:config>