1. AOP
1. AOP概念:面向切面编程。底层通过封装动态代理技术实现。
2.动态代理:在不修改源码的情况下,实现了方法的增强。
3.使用AOP技术,关注2点:
1).手动创建增强方法; 2).通过配置文件,告诉spring在哪些方法上使用增强方法。
1.1 动态代理
AOP面向切面编程的底层实现,AOP封装两种动态代理:
(1) proxy的动态代理(基于接口,jdk提供)
AccountService accountService = new AccountServiceImpl();
AccountService proxy = (AccountService)Proxy.newProxyInstance(
accountService.getClass().getClassLoader(),
new Class[] {accountService.getClass()},
new Invocationhandler(
public Object invoke(Proxy proxy,Method method,object[] args){
if("add".equals(method.getName())){
try(流对象){
method.invoke(accountService,args);
}catch{
}finally{
}
}else{
method.invoke(accountService,args);
}
return null;
}
)
);
proxy.add();
(2) Enhancer的动态代理(基于父类 cglib提供)
1.导入Cglib的包; 2.目标类不能被final关键字修饰
AccountService accountService = new AccountServiceImpl();
AccountService proxy = (AccountService)Enhancer.create(
accountService.getClass(),
new MethodInterceptor(
public object intercept(
Object Proxy,Method method,object[] arg,MethodProxy methodProxy){
if("add".equals(method.getName())){
try(流对象){
method.invoke(accountService,args);
}catch{
}finally{
}
}else{
method.invoke(accountService,args);
}
return null;
}
);
enhancer.add();
基于接口的Proxy动态代理,与目标类是兄弟关系;
基于父类的Enhancer动态代理,与目标类是父子关系,目标类为父类;
2. 基于全XML的AOP配置
实现步骤:
1.创建Maven工程,导入坐标。(IOC容器坐标、AOP坐标)
2.创建创建增强类,创建增强方法。创建被增强类,被增强方法。(不加注解,全XML的bean配置)
3.创建spring配置文件:配置通知、切入点。
<bean id="AccountService" class="cn.itcast.service.impl.AccountServiceImpl">
<bean id="logger" class="cn.itcast.untils.Logger">
<aop:config>
<aop:pointcut id="pt" expresition="excution( * cn.itcast..save(..))"/>
<aop:aspect ref="logger">
<aop:before method="before" pointcut-ref="pt"></aop:before>
<aop:after-returning method="afterReturning" pointcut-ref="pt"></aop:after-returning>
<aop:after-throwing method="afterThrowing" pointcut-ref="pt"></aop:after-throwing>
<aop:after method="after" pointcut-ref="pt"></aop:after>
<aop:around method="around" pointcut-ref="pt"></aop:around>
</aop:aspect>
</aop:config>
环绕通知的增强方法:
public void around(ProceedingJoinPoint joinPoint){
try {
System.out.println("前置通知(之前增强)");
joinPoint.proceed();
System.out.println("后置通知(之后增强)");
}catch (Throwable throwable){
System.out.println("异常通知(异常增强)");
}finally {
System.out.println("最终通知(最终增强)");
}
}
表达式语法:excution( * cn.itcast..AccountImpl.save(..))
最前边的*: 代表任意的返回值,public 省略没写。
.. 可以代替包名,代表任意包以及其子包
.. 可以代表参数,代表任意参数
* 可以代表包,代表任意包;可以代表类,任意类;代表方法名,任意方法名。
3. 基于半XML半注解的AOP配置
实现步骤:
1.创建Maven工程,导入坐标。(IOC容器坐标、AOP坐标)
2.创建增强类,创建增强方法。创建被增强类,被增强方法。(加注解,添加注解扫描context:component实现)
3.创建spring配置文件,配置IOC容器扫描,AOP开启注解。
<context:component-scan base-package="cn.itcast"></context:component-scan >
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
切面类注解(增强类):
类上:@Component(“id”) @Ascept
切面类方法上:
@pointcut("execution(* cn.itcast..save(..))")
Public void pointcut(){}
@Before("pointcut()")
@After-returning("pointcut()")
@After-throwing("pointcut()")
@after("pointcut()")
@Around("pointcut()")
4. 基于纯注解的AOP配置
实现步骤:
与3实现步骤几乎相同,只是想spring配置文件,换做配置类即可。测试的时候,加载配置类。
3.创建配置类SpringConfig类,添加注解实现配置文件中,以下配置。
<context:component-scan base-package="cn.itcast"></context:component-scan >
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
@Configuration
@ComponentScan
@EnableAspectJAutoProxy
public class SpringConfig{}
测试时,注解修改:
@Runwith(SpringJunit4ClassRunner.calss)
@ContextConfigration(classes=SpringConfig.class)
public class SpringJunit{ }
4.AOP专业术语–面试题
目标对象--Target: 要增强的对象
代理对象--Proxy : 增强后的代理对象
连接点--Joinpoint: 目标对象的所有方法
切入点--Pointcut: 目标对象中要被增强的方法(在增强类中配置)
通知--Advice: 自己写的增强方法
前置通知:在目标方法之前进行的增强方法
后置通知:在目标方法之后进行的增强方法
异常通知:在目标方法异常之时的增强方法
最终通知:在目标方法增强之后,一定会执行的方法
环绕通知:能够代替上面4个
Aspect(切面): 切入点+通知=切面 --> 被增强方法+增强方法==切面
Weaving(织入): 将切入点集成到切面的这一个过程,我们称为织入 -->目标方法+增强方法的合成过程==织入过程