aop及其实现的方法
aop 即 面向切面编程
横切关注点: 跨越应用程序的多个模块的方法或功能,与我们业务逻辑无关的,但是需要我们关注的部分,就是横切关注点。如日志,安全,缓存,事务等等。
切面(Aspect): 切面是一个横切关注点的模块化的特殊对象,即,他是一个类。
通知(advice): 切面必须完成的工作,即,他是一个方法。
目标(target): 被通知的对象。
代理(proxy): 向目标对象应用通知之后创建的对象。
切入点(pointcut): 切面通知执行的地点。
连接点(joinPoint): 被拦截到的程序执行点
AOP 主要用来解决,在不改变原有业务逻辑的情况下,增强横切逻辑代码,根本上解耦合,避免横切逻辑代码重复。
1、减少重复代码
2、提高开发效率
3、维护方便
准备工作
采用一个对用户的CRUD的例子
定义一个CRUD接口
public interface UserService {
void add();
void delete();
void update();
void select();
}
接口实现类
public class UserServiceImpl implements UserService{
@Override
public void add() {
System.out.println("增加了一个User!");
}
@Override
public void delete() {
System.out.println("删除了一个User!");
}
@Override
public void update() {
System.out.println("更新了一个User!");
}
@Override
public void select() {
System.out.println("查询了一个User!");
}
}
log类
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class Log implements MethodBeforeAdvice {
//method 要执行的目标对象的方法
//args 参数
//target 目标对象
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("[log] "+target.getClass().getName()+"的"+method.getName()+"被执行了");
}
}
AfterLog类
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
public class AfterLog implements AfterReturningAdvice {
//returnValue 返回值
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("执行了"+method.getName()+"返回的值为:"+returnValue);
}
}
配置spring applicationContext.xml
一定要导入AOP的约束
<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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd>
" userService" class="com.wq.service.UserServiceImpl"/>
<bean id="log" class="com.wq.log.Log"/>
<bean id="afterLog" class="com.wq.log.AfterLog"/>
beans>
测试类
import com.wq.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
@Test
public void test1(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.add();
}
}
配置xml如下
<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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="userService" class="com.wq.service.UserServiceImpl"/>
<bean id="log" class="com.wq.log.Log"/>
<bean id="afterLog" class="com.wq.log.AfterLog"/>
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* com.wq.service.UserServiceImpl.*(..) )"/>
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
aop:config>
beans>
测试示例
[log] com.wq.service.UserServiceImpl的add被执行了
增加了一个User!
执行了add返回的值为:null
自定义pointcut
public class DiyPointcut {
public void before(){
System.out.println("-------方法执行前------");
}
public void after(){
System.out.println("-------方法执行后------");
}
}
在xml中注册
xml配置如下
<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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="userService" class="com.wq.service.UserServiceImpl"/>
<bean id="log" class="com.wq.log.Log"/>
<bean id="afterLog" class="com.wq.log.AfterLog"/>
<bean id="diy" class="com.wq.diy.DiyPointcut"/>
<aop:config>
<aop:aspect id="diy" ref="diy">
<aop:pointcut id="point" expression="execution(* com.wq.service.UserServiceImpl.*(..))"/>
<aop:before method="before" pointcut-ref="point"/>
<aop:after method="after" pointcut-ref="point"/>
aop:aspect>
aop:config>
beans>
测试示例
-------方法执行前------
增加了一个User!
-------方法执行后------
自定义pointcut
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class AnnotationPointcut {
@Before("execution(* com.wq.service.UserServiceImpl.*(..))")
public void before(){
System.out.println("-------方法执行前------");
}
@After("execution(* com.wq.service.UserServiceImpl.*(..))")
public void after(){
System.out.println("-------方法执行后------");
}
}
这里采用的是注解方式实现的
@aspect
标注的是这个类是一个切面
@Before("execution(* com.wq.service.UserServiceImpl.*(..))")
与@After("execution(* com.wq.service.UserServiceImpl.*(..))")
与第二种方式的
<aop:pointcut id="point" expression="execution(* com.wq.service.UserServiceImpl.*(..))"/>
<aop:before method="before" pointcut-ref="point"/>
<aop:after method="after" pointcut-ref="point"/>
作用相同
xml配置如下
因为上面我采用的是全注解实现,所以需要添加注解的约束及配置
<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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com"/>
<context:annotation-config/>
<bean id="userService" class="com.wq.service.UserServiceImpl"/>
<bean id="log" class="com.wq.log.Log"/>
<bean id="afterLog" class="com.wq.log.AfterLog"/>
<aop:aspectj-autoproxy/>
beans>
测试示例
-------方法执行前------
增加了一个User!
-------方法执行后------