java 单继承多实现
1.AOP的引入
将系统业务逻辑和主业务逻辑拆解开,互不影响;通过继承系统业务逻辑的父类来实现系统业务逻辑的方法
2.AOP的概述
- 简介
AOP的底层,就是采用动态代理模式实现的,采用了两种代理:JDK的动态代理,与CGLIB的动态代理
AOP:面向切面编程,是面向对象OOP的一种补充,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
面向切面编程,就是将交叉业务逻辑封装成切面,利用AOP容器的功能将切面织入到主业务逻辑中,所谓交叉业务逻辑是指,通用的与主业务逻辑无关的代码,如安全检查,事务,日志等
-
.AOP基本术语
(1)切面:泛指交叉业务逻辑,日志处理事务处理就可理解为切面。常用的切面有通知和顾问,实际就是对主业务逻辑的一种增强。
(2)织入:指将切面代码插入目标对象的过程。
(3)连接点:指可以被切面织入的方法。通常业务接口中的方法均为连接点
(4)切入点:指切面具体织入的方法。在Student’ServiceImpl类中,若doSome()将被增强,而doOther()不被增强,则doSome为切入点,doOther为连接点
final修饰的方法不能作为切入点和连接点,因为不能修改增强
(5)目标对象:将要被增强的对象,即包含主业务逻辑的对象。Student’ServiceImpl的对象若被增器,则该类称为目标类,该类对象service称为目标对象。
(6)通知(Advice)
通知是切面的一种实现,可以完成简单的织入。通知定义了增强代码切入到目标代码的时间点
切入点定义切入的位置,通知定义切入时间
(7)顾问(Advisor)
通知是切面的另一种实现,能够将通知以更复杂的方式织入到目标对象,是将通知包装为更复杂切面的装配器。 -
AOP编程环境搭建
(1)导入jar包
Spring的基本jar和spring-aop-版本.jar,aop联盟的包com.springsource.org.aopalliance-版本.jar
(2)使用原beans的约束
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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">
</beans>
(3)注册类bean
3.通知Advice
常用通知:前置通知,后置通知,环绕通知,异常处理通知。
对于通知的定义,配置与使用,主要分为以下几步:
(1)前置通知MethodBeforeAdvice
定义前置通知。需要实现MethodBeforeAdvice接口,该接口中有一个方法before。
特点:在目标方法之前执行;不改变目标方法执行流程,不阻止目标方法执行;不改变目标方法执行结果
配置:(对象用ref,字符串用value')
<!-- 注册切面 -->
<bean id="beforeAdviceName" class=""/>
<!-- 通知:前置通知,通过动态代理实现,代理对象的生成 -->
<!-- 注意这里的ProxyFactoryBean不是代理类,而是代理对象生成器 -->
<!-- 故而并非是底层new了这个对象,而是工厂创建了这个 -->
<bean id="serviceProxy" class="org.springframework.aop.springframework.ProxyFactoryBean">
<property name="target" ref="目标对象someService"/>
<!-- 可以不写,因为其工厂类属性autodetectInterface=true默认自动检测接口 -->
<property name="interfaces" value="目标对象对应的接口ISomeService"/>
<property name="interceptorNames" value="beforeAdviceName"/>
</bean>
(2)后置通知AfterReturningAdvice
定义后置通知。需要实现AfterReturningAdvice接口,该接口中有一个方法AfterReturning。特点类似前置通知
(3)环绕通知MethodInterceptor
定义环绕通知。需要实现MethodInterceptor接口,环绕方法也叫方法拦截器,可在目标方法调用之前及之后做处理,可以改变目标方法的返回值。也可改变程序执行流程
public Object invoke(MethodInvocation invocation) throws Throwable(){
//目标方法执行前的操作
System.out.println("目标方法执行之前");
// 调用目标方法
Object res = invocation.proceed();
//处理目标方法结果
System.out.println("目标方法执行之后");
return res ;
}
(4)异常通知ThrowsAdvice
定义异常通知。需要实现ThrowsAdvice接口,该接口中有一个方法AfterReturning。
4 Advisor顾问
通知只能将只能将切面织入目标类的所有方法,不能织入指定方法
顾问对通知进行了包装,根据不同的通知类型,在不同的时间点,将切面织入到不同的切入点
PointcutAdvisor接口两个常用的实现类
NameMatchMethodPointcutAdvisor 名称匹配方法切入
RegexpPointcutAdvisor 正则表达式匹配切入
顾问里面需要传入通知类和切入点方法
5 自动代理生成器
(1)默认advisor自动代理生成器DefaultAdvisorAutoProxyCreator
底层是通过bean后处理器实现,产生相关目标对象代理,但他只找advisor切面,且会处理所有目标对象,无法挑选指定对象
(2)bean名称自动代理生成器BeanNameAutoProxyCreator
指定切面(interceptorNames,可是通知和顾问)织入指定目标对象(beanNames),传入的是数组,即支持多对多
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator" >
<property name="beanNames" value="Service"/>
<property name="interceptorNames" value="advisor"/>
</bean>
切面依赖目标对象的方法(切入点)
目标对象产生,bean后处理器实现自动生成代理,代理依赖目标对象和切面
这样最后形成连贯的指定切面切入指定目标对象的指定方法
有接口时默认使用jdk动态代理,没有接口默认使用CGLIB代理
有接口如何使用CGLIB代理?
<property name="proxyTargetClass" value="true"/>
或者优化
<property name="optimize" value="true"/>