一、动态代理
程序在整个运行过程中不存在目标类的代理类,目标对象的代理对象只是由生成工具在程序运行时创建,代理对象与目标对象的代理关系在程序运行时才确定。
项目开发中。我们经常感觉交叉业务与主业务深度耦合在一起,当交叉业务较多时,主业务代码会出现大量交叉业务逻辑代码,大大降低程序可读性,后期维护也不方便,增加开发难度,所以采用动态代理,在不修改主业务的前提下,对功能的扩展
二、AOP
是Spring框架的核心功能之一,面向切面编程是从动态角度去考虑程序的运行过程,利用AOP可以对主业务逻辑的各个部分进行隔离
【举个例子】 如果我们开发的是一个转账的业务是,在转账的痛死我能需要考虑权限控制,日志管理,加载事务等机制,那么在转账业务的开发过程中充斥着大量非主业务逻辑代码,这样导致我们代码可读性非常差,并且在实际的项目统计中,非业务逻辑代码往往可以占到这个代码量一半,大大增加我们的开发难度。
AOP面向切面编程
1、减少重复代码
2、专注业务
三、AOP面向切面编程
①切面ASpect
切面泛指交叉业务 , 即对主业务逻辑功能的增强
②连接点JoinPoint
连接点指可以被切面织入的具体方法,通常业务接口中的方法可以看做连接点
③切入点Pointcut
多个连接点的集合
【*】被标记为 final 的方法是不能作为连接点与切入点的。因为最终的是不能被修改的,不能被增强的。
④目标对象Target
指将要被增强的对象,即包含主业务逻辑的类的对象
⑤通知(Advice)
通知
定义了增强代码切入到目标代码的时间点,是目标方法执行之前执行,还是之后执行等。通知类型不同,切入时间不同。
切入点定义切入的位置,通知定义切入的时间。
AspectJ对AOP的实现
对于 AOP 这种编程思想,很多框架都进行了实现。Spring 就是其中之一,可以完成面向切面编程。然而,AspectJ 也实现了 AOP 的功能,且其实现方式更为简捷,使用更为方便,
而且还支持注解式开发。所以,Spring 又将 AspectJ 的对于 AOP 的实现也引入到了自己的框架中。在 Spring 中使用 AOP 开发时,一般使用 AspectJ 的实现方式。
官网 地址:http://www.eclipse.org/aspectj/
五、AspectJ的通知类型
AspectJ 中常用的通知有五种类型:
(1)前置通知
(2)后置通知
(3)环绕通知
(4)异常通知
(5)最终通知
applicationContext.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
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--声明目标类对象-->
<bean id="SomeServiceImpl" class="com.bjpowernode.ba01.SomeServiceImpl" />
<!--声明代理类对象-->
<bean id="Aspect" class="com.bjpowernode.ba01.MyAspect" />
<!--声明自动代理生成器,创建目标对象的代理类-->
<aop:aspectj-autoproxy proxy-target-class="true" />
</beans>
**
* @Aspect : 表示当前类是切面类
* 切面类, 是用来给业务方法增强功能的类, 把增强功能的代码写到切面类中
*/
@Aspect
public class MyAspect {
@Before(value = "execution(* *..SomeServiceImpl.do*(..))")
public void myBefore(JoinPoint jp){
//要增强的代码
System.out.println("执行增强功能的代码"+ new Date());
//查看当前正在执行的目标方法
System.out.println("执行方法:" + jp.getSignature().getName());
System.out.println("方法定义:" + jp.getSignature());
Object args[] = jp.getArgs();
StringBuilder buider = new StringBuilder();
for (Object arg : args) {
buider.append(arg).append("#");
}
System.out.println(buider.toString());
}
}
SomeService 接口
public interface SomeService {
void dosome(String name , int age);
}
接口实现类,需要被增强的类(目标类)
public class SomeServiceImpl implements SomeService {
@Override
public void dosome(String name, int age) {
System.out.println("执行了doSome方法添加业务的操作");
}
}
自定义一个测试类
public class ba01Test {
@Test
public void test01(){
String config = "applicationContext.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
SomeService proxy = (SomeService) ctx.getBean("SomeServiceImpl");
proxy.dosome("zhangsan", 20);
}
}
控制台输出结果:
执行增强功能的代码 2019-09-29 11:15:21
执行方法:dosome
方法定义:void com.bjpowernode.ba01.SomeServiceImpl.dosome(String,int)
zhangsan#20#
执行了doSome方法添加业务的操作
Process finished with exit code 0
后置通知
// AfterReturning
// returning 表示方法的形参 后面的值必须跟方法的形参名相同
@AfterReturning(
value = "execution(* *..SomeServiceImpl.doTwo(..))",
returning="ret"
)
public void MyAfterReturning(Object ret){
String param = null;
if (ret != null) {
param = (String) ret;
param = param.toUpperCase();
}
System.out.println(param);
}
@Aspect
public class MyAspect {
/*后置通知
* AfterReturning
* returning 表示方法的形参 后面的值必须跟方法的形参名相同
* */
@AfterReturning(
value = "execution(* *..SomeServiceImpl.doTwo(..))",
returning="ret"
)
public void MyAfterReturning(Object ret){
String param = null;
if (ret != null) {
param = (String) ret;
param = param.toUpperCase();
}
System.out.println(param);
}
}
ic class MyAspect {
/**
* @AfterThrowing:异常通知
* value 切入点表达式
* Throwing 自定义的变量名,表示目标方法抛出的异常对象,必须和方法的参数名一样
*特点 1.在目标方法抛出异常时执行的
* 2、可以看做是对目标方法的监控
* 3、不是异常处理程序,异常还是抛出了
*/
@AfterThrowing(
value="execution(* *..SomeServiceImpl.doFour(..))",
throwing ="ex"
)
public void MyAfterthrowing(Exception ex){
System.out.println("异常通知:在目标方法执行时出现了异常"+ ex);
}
}
/**
* @After 最终通知 表示程序执行结束后一定会执行的方法
*/
@After(value = "execution(* *..SomeService.doFive(..))")
public void MyAfter(){
System.out.println("最终通知,总是会执行的代码");
}
}
以上就是Spring-AOP面向切面编程
AOP 为 Aspect Oriented Programming 的缩写,意为:面向切面编程,可通过运行期动态代理实现程序功能的统一维护的一种技术。AOP 是 Spring 框架中的一个重要内容。利用 AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。