什么是AOP?
AOP是面向切面编程。在我们正常开发完成后,是纵向的,可能会增加需要并且要求不改变原有的代码逻辑。那么我们就需要横向的把这个新的功能点插入到原来纵向结构中,这样既保证了原有业务不动,又能添加新的功能。
此外,这样的插入并非静态的,而是动态的,即在运行时,动态的将代码插入到类的指定方法,指定位置的编程思想就是AOP。
因此,AOP并非Spring独有的,它是一种编程思想,只是说Spring的核心就是这一思想。
请注意,如果问到AOP,一定要说到动态代理,因为其本质就是动态代理。
如何在Spring中使用AOP
方式1:使用spring的API接口
即实现MethodBeforeAdvice和AfterReturningAdvice
导入依赖:
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
<scope>runtime</scope>
</dependency>
添加头文件
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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"> <beans>
类实现MethodBeforeAdvice来进行前置增强
public class Log implements MethodBeforeAdvice { // method: 要执行的目标对象的方法 // args: 参数 // target: 目标对象 @Override public void before(Method method, Object[] objects, Object target) throws Throwable { System.out.println(target.getClass().getName() + "的" + method.getName() + "被执行了"); } }
类实现AfterReturningAdvice来进行后置增强
public class AfterLog implements AfterReturningAdvice { @Override public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println("执行了" + method.getName() + "返回结果为:" + returnValue); } }
注册bean
<bean id="userService" class="com.kuang.service.UserServiceImpl"></bean> <bean id="log" class="com.kuang.log.Log"></bean> <bean id="afterLog" class="com.kuang.log.AfterLog"></bean>
配置aop
<aop:config> // 定义插入点 <aop:pointcut expression="execution(* com.kuang.service.UserServiceImpl.*(..)" id="pointcut"/> // 将增强插入到切入点,分别是之前和之后 <aop:advisor advice-ref="log" pointcut-ref="pointcut"/> <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/> </aop:config>
使用时,获取applicationContext, 获取service的bean对象,调用service里的方法,就会被自动增强。
public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService = (UserService) context.getBean("userService"); userService.add(); } }
方式2:自定义实现AOP
- 自定义一个类和方法:
```java
public class DiyPointCut {
public void before() {
}System.out.println("=====方法执行前=====");
public void after() {
System.out.println("=====方法执行后======");
}
}
2. 注册bean对象
```java
<bean id="diy" class="com.kuang.diy.DiyPointCut">
</bean>
- 通过aop配置进行切入
ps: 相对于方式1,更加简单一些。<aop:config> <aop:aspect ref="diy"> <aop:pointcut id="point" expression="execution(* com.kuang.service.UserService.*(..))"/> <aop:before method="before" pointcut-ref="point"/> <aop:after method="after" pointcut-ref="point"/> </aop:aspect> </aop:config>
方式3:通过注解实现AOP
添加自定义类,用@Aspect注解标注该类,用@Before或者@After来标注方法:
@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("这是注解, ====执行后===="); } }
注册该类的bean
<bean id="annotationPointCut" class="com.kuang.diy.AnnotationPointCut"></bean>
配置自动代理
<aop:aspectj-autoproxy/>