AOP
AOP作为spring的两大核心之一,即面向切面编程,它的底层实现是代理模式,横向的方式来对现有的功能进行加强,使业务逻辑和功能代码更好的脱耦合。
1 Aop在Spring中的作用
-
横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志 , 安全 , 缓存 , 事务等等 …
-
切面(ASPECT):横切关注点 被模块化 的特殊对象。即,它是一个类。
-
通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。
-
目标(Target):被通知对象。
-
代理(Proxy):向目标对象应用通知之后创建的对象。
-
切入点(PointCut):切面通知 执行的 “地点”的定义。
-
连接点(JointPoint):与切入点匹配的执行点。
SpringAOP中,通过Advice定义横切逻辑,Spring中支持5种类型的Advice:
2 AOP的使用
环境:需要导入jar包
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
第一种方式
- 通过继承已有的方法,然后通过AOP配置文件来设置切入面和执行环绕的方式
-
抽象接口UserService
public interface UserService { void add(); void delete(); void update(); void query(); }
-
真实角色(房东)
//真实对象,完成增删改查操作的人 public class UserServiceImpl implements UserService { public void add() { System.out.println("增加了一个用户"); } public void delete() { System.out.println("删除了一个用户"); } public void update() { System.out.println("更新了一个用户"); } public void query() { System.out.println("查询了一个用户"); } }
-
两个代理
public class AfterLog implements AfterReturningAdvice { @Override public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable { System.out.println("调用了"+o1.getClass().getName()+"的"+method.getName()+"方法,返回了"+objects); } }
public class BeforeLog implements MethodBeforeAdvice { //method : 要执行的目标对象的方法 //objects : 被调用的方法的参数 //Object : 目标对象 @Override public void before(Method method, Object[] objects, Object o) throws Throwable { System.out.println("调用了"+o.getClass().getName()+"的"+method.getName()+"方法,返回了"+objects); } }
-
通过bean配置的方式来实现代理和真实角色的联系
<?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--> <bean id="userService" class="com.lyj.service.UserServiceImpl"/> <bean id="beforeLog" class="com.lyj.method.BeforeLog"/> <bean id="afterLog" class="com.lyj.method.AfterLog"/> <!--aop的配置--> <aop:config> <!--切入点 expression:表达式匹配要执行的方法--> <aop:pointcut id="pointcut" expression="execution(* com.lyj.service.UserServiceImpl.*(..))"/> <!--执行环绕; advice-ref执行方法 . pointcut-ref切入点--> <aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/> <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/> </aop:config> </beans>
- 通过这样的一个方式,我们实现了之前和动态代理类似的功能。
第二种方式
有的时候它提供的代理方法可能不是很适配我们的功能需求,我们希望通过自定义代理类的方式来实现代理功能,而不是通过它现有的方法。
-
自定义的代理类Proxy
public class Proxy { public void BeforeMethod(){ System.out.println("好家伙,这是方法前"); } public void AfterMethod(){ System.out.println("好家伙,这是方法后"); } }
-
bean.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: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--> <bean id="userService" class="com.lyj.service.UserServiceImpl"/> <bean id="proxy" class="com.lyj.method.Proxy"/> <!--aop的配置--> <aop:config> <!--第二种方式:使用AOP的标签实现--> <aop:aspect ref="proxy"> <aop:pointcut id="pointcut" expression="execution(* com.lyj.service.UserServiceImpl.*(..))"/> <aop:before pointcut-ref="pointcut" method="BeforeMethod"/> <aop:after pointcut-ref="pointcut" method="AfterMethod"/> </aop:aspect> </aop:config> </beans>
第三种方式
通过注解的方式实现
@Aspect
public class AnnotationPointcut {
@Before("execution(* com.kuang.service.UserServiceImpl.*(..))")
public void before() {
System.out.println("---------方法执行前---------");
}
@After("execution(* com.kuang.service.UserServiceImpl.*(..))")
public void after() {
System.out.println("---------方法执行后---------");
}
@Around("execution(* com.kuang.service.UserServiceImpl.*(..))")
public void around(ProceedingJoinPoint jp) throws Throwable {
System.out.println("环绕前");
System.out.println("签名:" + jp.getSignature());
//执行目标方法
proceed Object proceed = jp.proceed();
System.out.println("环绕后");
System.out.println(proceed);
}
}
bean.xml
<!--第三种方式:注解实现-->
<bean id="annotationPointcut"class="com.lyj.method.AnnotationPointcut"/> <aop:aspectj-autoproxy/>