Spring的两大核心内容便是IoC和AOP,IoC我们已经了解过了,下面我们来看看AOP在Spring中的作用:提供声明式事务,允许用户自定义切面。AOP的内容
- 横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志,安全,缓存,事务等等...
- 切面(ASPECT) :横切关注点被模块化的特殊对象。即,它是一个类;
- 通知(Advice) :切面必须要完成的工作。即,它是类中的一个方法;
- 目标(Target) :被通知对象;
- 代理(Proxy) :向目标对象应用通知之后创建的对象;
- 切入点(PointCut) :切面通知执行的“地点”的定义;
- 连接点(JointPoint) :与切入点匹配的执行点;
下面我们来看一下AOP在Spring中是如何实现的,这里以日志来举例
前期准备
public interface UserDao { public void insert(); public void update(); public void delete(); public void query(); }
public class UserDaoImpl implements UserDao { public void insert() { System.out.println("增加一个用户"); } public void update() { System.out.println("更新一个用户"); } public void delete() { System.out.println("删除一个用户"); } public void query() { System.out.println("查询一个用户"); } }
1.方式一 -- 使用Spring的API接口
这里使用Spring定义好的API接口,自动进行处理
public class PreLogger implements MethodBeforeAdvice {
/**
*
* @param method 要执行的目标对象的方法
* @param objects 参数
* @param o 目标对象
* @throws Throwable
*/
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println(o.getClass().getName() + "执行了" + method.getName() + "方法");
}
}
public class PostLogger implements AfterReturningAdvice {
/**
*
* @param o 返回值
* @param method 目标对象的方法
* @param objects 参数
* @param o1 目标对象
* @throws Throwable
*/
public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
System.out.println(o1.getClass().getName() + "执行了方法:" + method.getName() + ",返回值为:" + o);
}
}
<?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"> <bean id="userDao" class="com.aircl.dao.UserDaoImpl"/> <bean id="preLogger" class="com.aircl.log.PreLogger"/> <bean id="postLogger" class="com.aircl.log.PostLogger"/> <aop:config> <aop:pointcut id="pointcut" expression="execution(* com.aircl.dao.UserDaoImpl.*(..))"/> <aop:advisor advice-ref="preLogger" pointcut-ref="pointcut"/> <aop:advisor advice-ref="postLogger" pointcut-ref="pointcut"/> </aop:config> </beans>
2.方式二 -- 自定义实现AOP
自定义一个类
public class DiyPointCut { public void before(){ System.out.println("===================方法执行前==================="); } public void after(){ System.out.println("===================方法执行后==================="); } }
<bean id="diyPointCut" class="com.aircl.log.DiyPointCut"/> <aop:config> <aop:aspect id="diyPointCutAspect" ref="diyPointCut"> <aop:pointcut id="pointcut" expression="execution(* com.aircl.dao.UserDaoImpl.*(..))"/> <aop:before method="before" pointcut-ref="pointcut"/> <aop:after method="after" pointcut-ref="pointcut"/> </aop:aspect> </aop:config>
3.方式三 -- 注解方式实现
使用注解方式实现时,需要提前开启AOP自动代理并将增强类注册到IoC中
<aop:aspectj-autoproxy/> <bean id="annotationPointCut" class="com.aircl.log.AnnotationPointCut"/>
然后编写增强类
@Aspect public class AnnotationPointCut { @Before("execution(* com.aircl.dao.UserDaoImpl.*(..))") public void before(){ System.out.println("===================方法执行前==================="); } @After("execution(* com.aircl.dao.UserDaoImpl.*(..))") public void after(){ System.out.println("===================方法执行后==================="); } }
4.拓展 -- execution表达式
链接:https://www.cnblogs.com/gdwkong/p/8660027.html