AOP:面向切面编程,其核心思想就是,将原本代码中的公共业务进行抽取,如:日志、事务、权限验证等;实现公共业务代码的复用性,并且使特定业务的功能更纯粹,关注点减少。
AOP的本质是通过动态代理实现,通过反射机制获取动态代理对象,实现对公共业务的抽取。
这里简单介绍一下AOP的一些专有名词。
横切关注点:就是一个功能,如:视图、权限验证、日志等,这里用权限验证举例;
切面(Aspect):实现权限验证的类,(Auth类);
通知(Advice):实现类中的方法,如:Auth类中的authenticate()方法;
目标:业务类的接口,如:user的接口;
代理:代理类 ---> 动态代理生成;
连接点、切入点: Auth类中的authenticate()方法在什么位置执行。
使用切面实现接口的方式实现:
1. 定义service接口
package com.yd.service;
public interface UserService {
public void add();
public void delete();
public void update();
public void query();
}
2. 编写service接口实现类
package com.yd.service;
public class UserServiceImpl implements UserService {
public void add() {
System.out.println("add");
}
public void delete() {
System.out.println("delete");
}
public void update() {
System.out.println("update");
}
public void query() {
System.out.println("query");
}
}
3. 编写切面实现接口
package com.yd.log;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class Log implements MethodBeforeAdvice {
public void log() {
System.out.println("log");
}
public void before(Method method, Object[] args, Object target) throws Throwable {
/**
* method: 被增强的方法
* args: 被增强方法的参数列表
* target: 被增强的方法所属类的对象
*/
log();
}
}
org.springframework.aop.AfterAdvice ----> 方法执行后的增强
org.springframework.aop.AfterReturningAdvice ----> 带有返回值的方法执行后的增强,方法默认返回值为null
org.springframework.aop.MethodBeforeAdvice -----> 方法执行之前的增强
4. 配置spring.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
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.yd.service.UserServiceImpl"/>
<bean id="log" class="com.yd.log.Log"/>
<!--配置aop-->
<aop:config>
<!--配置切入点-->
<aop:pointcut id="pointcut" expression="execution(* com.yd.service.UserServiceImpl.*(..))"/>
<!--配置环绕增强-->
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
</aop:config>
</beans>
5. 编写测试类
import com.yd.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
@Test
public void test() {
// 创建上下文对象
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
// 获取bean对象并强转成接口对象,因为动态代理是代理接口创建代理类的
UserService userService = (UserService) context.getBean("userService");
userService.add();
}
}