cglib代理
动态代理有个约束:目标对象一定是要有接口的,没有接口就不能实现动态代理…..----->因此出现了cglib代理
cglib代理也叫子类代理,从内存中构建出一个子类来扩展目标对象的功能!
-
CGLIB是一个强大的高性能的代码生成包,它可以在运行期扩展Java类与实现Java接口。它广泛的被许多AOP的框架使用,例如Spring AOP和dynaop,为他们提供方法的interception(拦截)
写cglib代理步骤:
-
需要引入cglib – jar文件, 但是spring的核心包中已经包括了cglib功能,所以直接引入spring-core-3.2.5.jar即可。
-
引入功能包后,就可以在内存中动态构建子类
-
代理的类不能为final,否则报错【在内存中构建子类来做扩展,当然不能为final,有final就不能继承了】
-
目标对象的方法如果为final/static, 那么就不会被拦截,即不会执行目标对象额外的业务方法。
AOP
Aop: aspect object programming 面向切面编程
-
功能: 让关注点代码(重复代码)与业务代码分离!
-
面向切面编程就是指: 对很多功能都有的重复的代码抽取,再在运行的时候往业务方法上动态植入“切面类代码”。
步骤:
-
1、引入aop相关jar文件 (aspectj aop优秀组件)
-
spring-aop-3.2.5.RELEASE.jar 【spring3.2源码】
-
aopalliance.jar 【spring2.5源码/lib/aopalliance】
-
aspectjweaver.jar 【spring2.5源码/lib/aspectj】或【aspectj-1.8.2\lib】
-
aspectjrt.jar 【spring2.5源码/lib/aspectj】或【aspectj-1.8.2\lib】
-
-
2、bean.xml中引入aop声明
<beans
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
</beans>
注解:
-
@Aspect 指定一个类为切面类
-
@Pointcut("execution(* cn.itcast.e_aop_anno.*.*(..))") 指定切入点表达式
-
Pointcut定义时,还可以使用&&、||、! 这三个运算
@Pointcut("logSender() || logReceiver()")
private void logMessage(){}-
还可以将一些公用的Pointcut放到一个类中,以供整个应用程序使用,在使用时,指定完整的类名加上Pointcut签名就可以了
@Before("bean.Pointcuts.logMessage()")
public void before() {
} -
-
@Before("pointCut_()") 前置通知: 目标方法之前执行
-
@After("pointCut_()") 后置通知:目标方法之后执行(始终执行)
-
@AfterReturning("pointCut_()") 返回后通知: 执行方法结束前执行(异常不执行)
-
@AfterThrowing("pointCut_()") 异常通知: 出现异常时候执行
-
@Around("pointCut_()") 环绕通知: 环绕目标方法执行,使用该注解的方法必须传入ProceedingJoinPoint对象,并调用它的proceed()方法(执行目标方法)
@Pointcut表达式解析 execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?)
括号中各个pattern分别表示:
-
修饰符匹配(modifier-pattern?),可省略不写
-
返回值匹配(ret-type-pattern)可以为 * 表示任何返回值,全路径的类名等
-
类路径匹配(declaring-type-pattern?),bean.* 表示bean包下的所有类
-
方法名匹配(name-pattern)可以指定方法名,* 代表所有, set* 代表以set开头的所有方法
-
参数匹配((param-pattern))可以指定具体的参数类型,多个参数间用 “,” 隔开,各个参数也可以用 “ * ” 来表示匹配任意类型的参数,如(String)表示匹配一个String参数的方法;(*,String) 表示匹配有两个参数的方法,第一个参数可以是任意类型,而第二个参数是String类型;可以用(..)表示零个或多个任意参数
-
异常类型匹配(throws-pattern?)
-
其中后面跟着“?”的是可选项
@Component
@Aspect
public class AOP {
//定义切入点
@Pointcut("execution(* bean.*.*(..))")
public void pt(){}
//可以直接写切入点表达式
@Before("execution(* bean.*.*(..))")
public void before(){
System.out.println("开始事务");
}
//使用定义好的切入点
@After("pt()")
public void after(){
System.out.println("关闭事务");
}
@Around("pt()")
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕前...");
//必须传入ProceedingJoinPoint对象,调用proceed()方法 来执行目标方法
joinPoint.proceed();
System.out.println("环绕后...");
}
}