Spring—静态代理,动态代理及AOP开发
静态代理
由于我们的项目当中会存在一些除了核心业务功能之外的额外功能,这些额外功能在某些情况下是需要的
,在有些情况下还不需要。我们的想法是在需要的时候加上额外功能,不需要的时候拿掉额外功能,如何
使我们的代码可以灵活的使用额外功能?
2.通过代理类给原始类增加额外功能。
2.1代理类与原始类要实现同一个接口
2.2 代理类要保留对原始类的引用 意思是保留原始类的核心功能
3. 静态代理类的缺陷太过明显,有以下几点缺陷
3.1 代理类的数量会随着原始类的增加,越来越多
3.2 额外功能冗余,因为每个功能如果都要使用额外功能的话就会重复调用
AOP开发
1. AOP简介
1.1 Aop(Aspect Oriented Programming) 是面向切面编程
面向切面编程:面向切面编程主要是用来解决开发中的一些问题
1.2 OOP(Object Oriented Programming) 面向对象编程: 面向对象编程主要
是以多个对象之间的相互协作解决一些问题。
2. Spring 的AOP 开发是基于Spring 的动态代理实现的。
动态代理是在程序运行的过程中生成的代理类对象
动态代理的目的也是通过代理类给原始类(目标类)增加额外功能
3. Spring 动态代理的开发
3.1 编写原始类 (service层)
package cn.huiani.service;
/**
* @Auther: zyh(huiani.cn)
* @Date: 2019/10/30
* @Description: cn.huiani.service
* @version: 1.0
*/
public class SpringAopServiceImpl implements SpringAopService {
@Override
public void add() {
System.out.println("阳阳我儿乖乖");
}
@Override
public void modify() {
System.out.println("阳阳我儿乖乖");
}
}
3.2 Spring配置文件中配置原始类配置 用来创建对象
<bean id="springAopService" class="cn.huiani.service.ProductServiceImpl"></bean>
3.3 编写通知类(额外功能类)
通知类分类:
- 前置通知:在原始方法执行前加入额外功能
- 后置通知:在原始方法执行后加入额外功能
- 环绕通知:在原始方法的前和后都加入额外功能
- 异常通知:在原始方法执行异常时加入额外功能
以下是前置通知案例:
前置通知类:
package cn.huiani.advice;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
/**
* @Auther: zyh(huiani.cn)
* @Date: 2019/10/30
* @Description: cn.huiani.advice
* @version: 1.0
*/
public class MyBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("我是前置通知+++我在方法执行前执行");
}
}
3.4 定义切入点:用于指定额外功能加入的位置。(加入到哪些包中,哪些类中,哪些方法上)
切入点函数(重要)
- execution(* *..*.*(..)) 匹配所有包中的所有类中的所有方法(包含子包)
- execution(**.*.*(..)) 不包含子包
有关函数中*符号的解释
第一个* 匹配方法的返回值类型和修饰符
第二个* 匹配包结构
第三个* 匹配类名
第四个* 匹配方法名
(..)配皮参数列表
举例:execuftion(*cn.huiani.service..*.*(..))匹配cn.huiani.service包以下所有类中的所有方法
execution(* *..ProductServiceImpl.*(..)) 匹配任意包下类名是ProductServiceImpl类中的所有方法
execution(* *..*.removeOrder(..)) 匹配任意包下 任意类中 方法名是removeOrder的。
execution(* *..*.*(Integer)) 匹配只有一个Integer类型参数的方法
execution(* *..*.*(Integer,..)) 匹配第一个参数是Integer类型的方法
II、within(*..*) : 匹配所有包下所有的类
第一个* 匹配包结构, 第二个* 匹配类名, 中间两个点代表匹配子包
within(com.baizhi.service..*) 匹配com.baizhi.service包以及其子包下的所有的类
within(*..ProductServiceImpl) 匹配任意包下的类名是ProductServiceImpl的类
III、args(..) : 匹配任意参数的方法
args(Integer,..) 匹配第一个参数是
Integer类型的方法,不在乎后面参数的类型和个数
IV、@annotation(注解的类型) : 用于匹配使用了指定类型注解的方法
@annotation(com.baizhi.annotation.Value) 匹配方法上使用了Value注解的。
切入点函数运算符:
and 并且
or 或者
3.5 编织-wave;根据切入点指定的位置,将指定的额外功能加入
<aop:config>
<!--定义切入点
id 属性是引用切入点的依据
expression 属性用于定义切入点表达式
-->
<aop:pointcut id="pct" expression="execution(* cn.huiani.service..ProductServiceImpl.*(..))"></aop:pointcut>
<!--编织-->
<aop:advisor advice-ref="beforeAdvice" pointcut-ref="pct"></aop:advisor>
</aop:config>
3.6 获取代理类的对象进行测试
import cn.huiani.service.SpringAopService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @Auther: zyh(huiani.cn)
* @Date: 2019/10/30
* @Description: PACKAGE_NAME
* @version: 1.0
*/
public class SpringAopTest {
@Test
public void test0(){
// 此时是基于动态代理的开发,获取的是动态代理的类
// 动态代理的类是在程序运行的过程中创建的
ApplicationContext cxt=new ClassPathXmlApplicationContext("spring-aop.xml");
SpringAopService springAopService = (SpringAopService) cxt.getBean("springAopService");
springAopService.add();
}
}
运行结果
我是前置通知+++我在方法执行前执行
阳阳我儿乖乖
AOP总结
一、AOP【重点】
1.编写原始类
2.编写通知
2.1 前置通知 MethodBeforeAdvice
2.2 后置通知 AfterReturningAdvice
2.3 环绕通知 MethodInterceptor
2.4 异常通知 ThrowsAdvice
3.定义切入点: 指定额外功能加入的位置。
execution(* *..*.*(..))
within(*..*)
args(..)
@annotation(..)
4.编织: 将指定的通知(额外功能)按照切入点的定义加入。
5.获取代理类的对象进行测试 : 通过Spring的AOP编程配置,我们从工厂可以直接拿到代理类的对象。
二、AOP小结
1.AOP称为面向切面编程,Spring的AOP是基于动态代理实现的,通过代理类给原是类增加额外功能。 所谓的面相切面编程其实是指额外功能与切入点组装到一起形成的一个切面。
2. AOP编程的好处: 使用AOP编程的思想, 可以使额外功能与核心的业务功能完全的从编码上剥离开,可以让我们的程序员更加的专注于业务功能的实现。
额外功能的定义,被提取到了一个地方。 解决了曾经横切入项目中的冗余代码,提高了代码的复用性。
三、Spring动态代理的实现原理 【了解】
1. JDK动态代理实现 : 原是类和代理类实现同一个接口。
2. cglib动态代理的实现: 要求代理类去继承原始类。
ps: Spring在生成代理类的对象的时候,会根据原是类是否实现了接口来决定采用JDK的方式还是Cglib的方式生成代理类的对象 。