使用Spring实现Aop三种方法
使用Spring实现Aop三种方法
**
方式一 :使用spring的AP接口
方式二 : 自定义来实现AOP (主要是切面定义)
方式三 :使用注解实现AOP
**
文章目录
- 使用Spring实现Aop三种方法
- 前言
- jar 依赖
- 方式一 :使用spring的AP接口
- 方式二 :自定义来实现AOP (主要是切面定义)
- 方式三 :使用注解实现AOP
- 发现问题:
- 解决方法
前言
jar 依赖
使用AOP 植入 ,需要导入依赖包aspectj
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.8</version>
<scope>runtime</scope>
</dependency>
方式一 :使用spring的AP接口
定义uservice接口
public interface uservice {
public void add();
public void update();
public void delete();
public void select();
}
接口实现类userviceImpl
public class userviceImpl implements uservice {
@Override
public void add() {
System.out.println("增加");
}
@Override
public void update() {
System.out.println("修改");
}
@Override
public void delete() {
System.out.println("删除");
}
@Override
public void select() {
System.out.println("查询");
}
}
创建要做代理 为uservice 添加日志 的log类
public class Log implements MethodBeforeAdvice {
/*
* method :要执行的对象发法
*args 参数
* target 目标对象
* */
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println(target.getClass().getName()+"的"+method.getName());
}
}
创建afterlog 类
public class afterLog implements AfterReturningAdvice {
@Override//returnValue返回值
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("执行了"+method.getName()+"返回了"+returnValue);
}
}
ben.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="uservice" class="com.powernode.demo04.userviceImpl"/>
<bean id="log" class="com.powernode.demo04.Log"/>
<bean id="after" class="com.powernode.demo04.afterLog"/>
<!-- 方式一 使用原声spring API 接口 -->
<!-- 配置Aop 需要导入Aop约束-->
<aop:config>
<!-- 切入点 pointcut:表达式 execution 要执行的位置-->
<aop:pointcut id="pointcut" expression="execution(* com.powernode.demo04.userviceImpl.*(..))"/>
<!-- 执行环绕增强 -->
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="after" pointcut-ref="pointcut"/>
</aop:config>
</beans>
创建测试:
public class test {
public static void main(String[] args) {
//
ApplicationContext Context = new ClassPathXmlApplicationContext("bean.xml");
//动态代理代理的是接口
uservice uservice = Context.getBean("uservice", uservice.class);
uservice.add();
}
}
方式二 :自定义来实现AOP (主要是切面定义)
div 自定义一个类
public class div {
public void before(){
System.out.println("方式二 ---- 之前");
}
public void after(){
System.out.println("方式二 ---- 之后");
}
}
bean.xml
<!-- 方式二 :自定义来实现AOP (主要是切面定义) -->
<bean id="div" class="com.powernode.demo04.div"/>
<aop:config>
<!-- 自定义切面 ref 要引用的类 -->
<aop:aspect ref="div">
<!-- 切入点 -->
<aop:pointcut id="pointcut" expression="execution(* com.powernode.demo04.userviceImpl.*(..))"/>
<!-- 要加入的发法 -->
<aop:after method="after" pointcut-ref="pointcut"/>
<aop:before method="before" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
测试结果:
分析:
方式三 :使用注解实现AOP
创建annotation类
package com.powernode.demo04;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect // 标志这个类是一个切面
public class annotation {
@Before("execution(* com.powernode.demo04.userviceImpl.*(..))")
public void before() {
System.out.println("---- 发法执行前-----");
}
@After("execution(* com.powernode.demo04.userviceImpl.*(..))")
public void after() {
System.out.println("---- 发法执行后-----");
}
// 加入环绕增强
@Around("execution(* com.powernode.demo04.userviceImpl.*(..))")
public void around(ProceedingJoinPoint jp) throws Throwable {
System.out.println("环绕前");
// 执行发法
Object proceed = jp.proceed();
System.out.println("环绕后");
}
}
bean.xml
<!-- 方式三 使用注解 -->
<bean id="annotation" class="com.powernode.demo04.annotation"/>
<!-- 开启注解 JDK(默认 expose-proxy="false" ) cglib(expose-proxy="true") -->
<aop:aspectj-autoproxy expose-proxy="false"/>
测试:
public static void main(String[] args) {
//
ApplicationContext Context = new ClassPathXmlApplicationContext("bean.xml");
//动态代理代理的是接口
uservice uservice = Context.getBean("uservice", uservice.class);
uservice.add();
}
}
执行顺序 :环绕前 – 执行前 – 方法 --执行后 – 环绕后
代码分析:
发现问题:
发现@Aspect注解无法进行解析,Cannot resolve symbol ‘Aspcet’。
解决方法
导入的依赖aspect包
这个依赖时,多了个 runtime属性,发现它:
一般是运行和测试环境使用,编译时候不用加入classpath,打包时候会打包到目标包中。一般是通过动态加载或接口反射加载的情况比较多。也就是说程序只使用了接口,具体的时候可能有多个,运行时通过配置文件或jar包扫描动态加载的情况。典型的包括:JDBC驱动等。
于是将这一行代码注释掉,@Aspect注解添加成功!
CSDN-Ada助手: 推荐 OpenCV 技能树:https://edu.csdn.net/skill/opencv?utm_source=AI_act_opencv
无心法师979: 本方法我已解决
Avengerrr: 笑死,我按这个流程不行。 反而卸载后重新安装cli,成功了。
然鹅80: 一样的情况
只会log: 大佬,我跟你这个操作一步来的,没用呀