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(); } }