Spring AOP(一)
什么是AOP?
相对op而言,传统的OOP开发中的代码逻辑是自上而下的,而这些过程会产生一些横切性问题.业务流程中,会产生一些横切性的问题,例如织入日志,权限调用,事务处理,性能检查等.不会影响主业务逻辑,例如记录日志错误,不会对主业务逻辑有影响.AOP的编程思想就是把与业务无关的操作和主业务逻辑分开,达到与主业务逻辑解耦的目的。使代码的重用性和开发效率更高。
Spring AOP的概念
切面:概念,是连接点,切点、通知的载体,在AspectJ是一种类来表现,在Spring XML是一种标签,抽象的
连接点:是一个方法的执行,例如日志文件通过aop增强到controller中的login方法,这个login方法称为连接点。连接点是目标对象的方法*
切点:切点就是连接点的集合,例如关注切面编程,AOP增强到哪里去
织入:把代理逻辑加入到目标对象上的过程叫做织入
目标对象:目标对象 原始对象
代理对象:包含了原始对象的代码和增强后代码的那个对象
通知:advice通知类型:
Before 连接点执行之前,但是无法阻止连接点的正常执行,除非该段执行抛出异常
After 连接点正常执行之后,执行过程中正常执行返回退出,非异常退出
After throwing 执行抛出异常的时候
After (finally) 无论连接点是正常退出还是异常退出,都会执行
Around advice: 围绕连接点执行,例如方法调用。这是最有用的切面方式。around通知可以在方法调用之前和之后执行自定义行为。它还负责选择是继续加入点还是通过返回自己的返回值或抛出异常来快速建议的方法执行。
AspectJ
AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法,它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。AspectJ是一种AOP技术。Spring借助了AspectJ的语法,@AspectJ
Spring AOP和AOP有什么关系?
AOP是一种思想,是编程需要的达到的目标,Spring Aop是一种实现AOP的技术。AspectJ也能实现AOP。
Spring使用AOP
一、开启AOP:
- 方法1、Java Configuration
@Configuration
@EnableAspectJAutoProxy
public class AppConfig {
}
- 方法2、XML Configuration
<aop:aspectj-autoproxy/>
二、声明切面
定义bean(@Component)添加@Aspect
<bean id="myAspect" class="org.xyz.NotVeryUsefulAspect">
<!-- configure properties of the aspect here -->
</bean>
三、定义切点
切点是连接点的集合,所以@Pointcut("")里面添加连接点
@Pointcut("execution(* transfer(..))") // the pointcut expression
private void anyOldTransfer() {} // the pointcut signature
切点指示器:
execution:用于匹配方法执行连接点。这是使用Spring AOP时要使用的主要切入点指示符
(用法:execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern)
throws-pattern?)
- modifiers-pattern:方法的可见性,如public,protected;
- ret-type-pattern:方法的返回值类型,如int,void等;
- declaring-type-pattern:方法所在类的全路径名,如com.spring.Aspect;
- name-pattern:方法名类型,如buisinessService();
- param-pattern:方法的参数类型,如java.lang.String;
- throws-pattern:方法抛出的异常类型,如java.lang.Exception;
)
within:将匹配限制为特定类型中的连接点(使用Spring AOP时,在匹配类型中声明的方法的执行)。最小粒度为类。
两者区别:within与execution相比,粒度更大,仅能实现到包和接口、类级别。而execution可以精确到方法的返回值,参数个数、修饰符、参数类型等
args: args表达式的作用是匹配指定参数类型和指定参数数量的方法,与包名和类名无关。例@Pointcut(args(java.io.Serializable))
this:JDK代理时,指向接口和代理类proxy,cglib代理时 指向接口和子类(不使用proxy)。例:@Pointcut(“this(com.chenss.dao.IndexDaoImpl)”)//当前对象,也就是代理对象,代理对象时通过代理目标对象的方式获取新的对象,与原值并非一个
target:指向接口和子类。例:@Pointcut(“target(com.dao.IndexDaoImpl)”)//目标对象,也就是被代理的对象。限制目标对象为com.dao.IndexDaoImpl类
四、定义通知
切点上面的连接点作用到通知
@Aspect
public class BeforeExample {
@Before("com.xyz.myapp.CommonPointcuts.dataAccessOperation()")
public void doAccessCheck() {
// ...
}
}
Spring中的还可以有以下使用
@Pointcut("execution(public * *(..))")
private void anyPublicOperation() {}
@Pointcut("within(com.xyz.myapp.trading..*)")
private void inTrading() {}
@Pointcut("anyPublicOperation() && inTrading()")
private void tradingOperation() {}
例如: @Before(“com.xyz.myapp.CommonPointcuts.dataAccessOperation()&&com.xyz.myapp.CommonPointcuts.dataAccessOperation2()”) 能进行条件的判断。
JDK动态代理的为什么是基于接口的,为什么不基于继承?
用ProxyGenetaor.generateProxy(“xxx”,Class<?>[]);获取代理类的字节数组。写入.class,反编译后能发现这个生成的代理类是继承Proxy,因为java单继承,所以不能基于继承。@EnableAspectJAutoProxy(proxyTargetClass = true)CGLib动态代理,默认为false
创作不易,转载请注明出处!