文章目录
1.Aop的概念:
AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
其实就是对原来业务层的代码,通过动态代理的方式,在原有的业务代码上中下插入新的功能或者修改公共功能。
这张图就是解释在curd操作中添加日志的过程,其实就是一个动态代理实现的过程
2 .Aop在Spring中的作用
提供声明式事务;允许用户自定义切面
- 横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志 , 安全 , 缓存 , 事务等等 …
- 切面(ASPECT):横切关注点 被模块化 的特殊对象。即,它是一个类。
- 通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。
- 目标(Target):被通知对象。
- 代理(Proxy):向目标对象应用通知之后创建的对象。
- 切入点(PointCut):切面通知 执行的 “地点”的定义。
- 连接点(JointPoint):与切入点匹配的执行点。
SpringAOP中,通过Advice定义横切逻辑,Spring中支持5种类型的Advice:
3.在使用Spring实现AOP
重要的第一步导入织入jar坐标
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
以及spring所需要的jar包:
防止静态资源过滤:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
3.1方法一:切点类
使用Spring的API 接口 【主要SpringAPI接口实现】
步骤:
-
创建业务模块的接口和实现类
业务接口 public interface Userservice { void add(); void del(); void udp(); void sel(); } 业务的实现类 public class UserserviceImpl implements Userservice { public void add() { System.out.println("增加"); } public void del() { System.out.println("删除"); } public void udp() { System.out.println("更改"); } public void sel() { System.out.println("查询"); } }
-
编写切点类实现api接口
//实现Spring的接口 public class Beforcutpoint implements MethodBeforeAdvice { public void before(Method method, Object[] objects, Object o) throws Throwable { //增加功能,我在这里增加的是一个类似于日志功能 //打印使用了何种方法 System.out.println("debug"+"=="+method.getName()); } }
-
编写xml配置文件
注意首先需要导入aop的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 http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <!--在xml中先将有关系的类放到ioc中--> <bean id="beforcunpoint" class="com.g.cunpoint.Beforcutpoint"/> <bean id="userservice" class="com.g.Service.UserserviceImpl"/> <!--设置插入点--> <aop:config> <!--设置切入的位置,起名字为pointcut,表达式中的是切入的位置,*(..)表示该类下的所有的方法都切入--> <aop:pointcut id="pointcut" expression="execution(* com.g.Service.UserserviceImpl.*(..))"/> <!--引入需要插入的功能类,我在此处是使用了MethodBeforeAdvice在方法前插入的方法--> <aop:advisor advice-ref="beforcunpoint" pointcut-ref="pointcut"/> </aop:config> </beans>
-
测试
public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Userservice userservice=context.getBean("userservice", Userservice.class); userservice.add(); } }
-
结果:
debug==add 增加
3.2方法二:切面类(类中包含多个点)
步骤:
-
创建业务模块的接口和实现类(与上面一致)
-
创建切面(自定义类)
public class Aspectcut { public void befor(){ System.out.println("原业务之前"); } public void after(){ System.out.println("原业务之后"); } }
-
编写xml配置文件
<bean id="uservice" class="com.g.Service.UserserviceImpl"/> <bean id="aspectcut" class="com.g.Aspectcut.Aspectcut"/> <aop:config> <aop:aspect ref="aspectcut"> <aop:pointcut id="point" expression="execution(* com.g.Service.UserserviceImpl.*(..))"/> <aop:before method="befor" pointcut-ref="point"/> <aop:after method="after" pointcut-ref="point"/> </aop:aspect> </aop:config>
-
测试
public class MyTest { public static void main(String[] args) { ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("aplicationxml.xml"); Userservice userservice=context.getBean("uservice", Userservice.class); userservice.add(); } }
3.3方法三:切面注解版
-
创建业务模块的接口和实现类(与上面一致)
-
创建切面(自定义类)使用注解
@Aspect public class AnnAspect { @After("execution(* com.g.Service.UserServiceImpl.*(..))") public void after(){ System.out.println("方法执行后"); } @Before("execution(* com.g.Service.UserServiceImpl.*(..))") public void before(){ System.out.println("方法执行前"); } @Around("execution(* com.g.Service.UserServiceImpl.*(..))") public void around(ProceedingJoinPoint joinPoint) throws Throwable{ System.out.println("环绕前"); joinPoint.proceed(); System.out.println("环绕后"); } }
-
xml中配置
先将需要实现对象的类放到Ioc中 <bean id="annaop" class="com.g.log.AnnAspect"/> <bean id="userservice" class="com.g.Service.UserServiceImpl"/> 开启注解支持,自动代理 <aop:aspectj-autoproxy/>
-
测试
public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("aopconfig.xml"); UserService userservice = context.getBean("userservice", UserService.class); userservice.add(); } }
-
结果:
环绕前 方法执行前 增加了一个用户 环绕后 方法执行后