Spring第三天(AOP)
- 创建对象的注解:@Component,@Controller,@Service,@Repository (属性value)
- 依赖注入的注解:@Autowired,@qualifier(value=”id”),@Resource(value=”id”),@Value(“${jdbc.username}“)
- 生命周期的注解:@Scope @PostConstruct @PreDestroy
- 纯注解编程:@Configuration,@ComponentScan,@PropertySource,@Import,@Bean
- 单元测试的注解:(固定)@Runwith(SpringJunit4ClassRunner.class)@ContextConfiguration( locations | classes)
一 动态代理
动态代理:在不改变源代码的前提下对方法进行增强。
需求:对账户的方法(save)进行增强
- 被代理对象方法之前增强
- 被代理对象方法之后增强
- 抛出异常增强
- 在finally代码块中增强
基于接口的动态代理(JDK动态代理)
条件:要有接口
生成的动态代理对象和被代理对象是兄弟关系
基于子类的动态代理(cglib的动态代理)
条件:被代理对象不能使用final修饰
导入cglib的坐标 通过cglib的一个工具类(Enhancer)
生成的动态代理对象是被代理对象的子类
AOP的底层会自动抉择
如果被增强的对象有接口 会选择jdk的动态代理
如果被增强的对象没有接口 会选择cglib的动态代理 (此时导入cglib的坐标)
二 Spring中AOP的相关概念
AOP的相关的专业术语(面试题)
Target(目标对象): 要增强的对象
Proxy(代理对象) : 对目标对象的增强封装
Joinpoint(连接点): 目标对象的所有方法
Pointcut(切入点): 要被增强的方法
Advice(通知/增强): 增强的那段代码方法
前置通知:在目标方法之前进行通知的增强
后置通知:在目标方法之后进行通知的增强
异常通知:在目标方法发生了错误进行通知的增强
最终通知:在目标方法执行完毕进行通知的增强
环绕通知:能够代替上面4个
Aspect(切面): 切入点+通知=切面
目标方法和增强方法合成在一起 叫做切面
Weaving(织入):将切入点集成到切面的这一个过程 我们称为织入过程
将目标方法和增强方法合成在一起的过程 叫织入过程
底层实现技术就是动态代理
三 AOP的配置
案例:对账户的方法(save)进行增强
被代理对象方法之前增强(前置通知)
被代理对象方法之后增强(后置通知)
抛出异常增强(异常通知)
在finally代码块中增强(最终通知)
Aop的XML方式:
1 导入aop的坐标
2 自己需要创建增强方法(通知)--定义一个类写通知
---写了通知的类要交给ioc容器管理
3 在spring的配置文件中配置哪些通知在那些切入点之前或之后或异常或最终增强
---spring底层自动使用动态代理进行增强
3.1 基于xml的配置
<!--1.将切面类交给spring容器管理-->
<bean id="logger" class="cn.itcast.utils.Logger"></bean>
<!--使用aop的名称空间 -->
<!--
声明AOP配置
-->
<aop:config>
<!--配置切入点
id:切入点的唯一标识
expression:切入点表达式
完整写法:execution(方法的修饰符 方法的返回值 类的全类名.方法名(参数))
支持通配符的写法:
* : 标识任意字符串
.. : 任意重复次数
1. 方法的修饰符可以省略:void cn.itcast.service.impl.AccountServiceImpl.saveAccount()
2. 返回值可以使用*号代替:标识任意返回值类型
* cn.itcast.service.impl.AccountServiceImpl.saveAccount()
3. 包名可以使用*号代替,代表任意包(一个包使用一个*)
4. 使用..配置包名,标识此包以及此包下的所有子包
5. 类名可以使用*号代替,标识任意类
6. 方法名可以使用*号代替,表示任意方法
7. 可以使用..配置参数,任意参数
-->
<aop:pointcut id="pt" expression="execution(* cn.itcast.service.impl.*.*(..))"></aop:pointcut>
<!--配置切面
ref:切面类的唯一标识
-->
<aop:aspect ref="logger">
<!--配置通知类型 :前置通知
method : 切面类中的方法
pointcut-ref:切入点唯一标识
<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>
3.2 基于注解结合xml的配置
注解:
Ioc的注解
AOP的注解
*开启注解们的支持
1.包扫面
2.开启对AOP注解的支持
注解:
@Aspect : 声明切面类
@PonitCut:定义公共的切入点
配置到空方法上,value:切入点表达式
引用:方法名()
配置通知类型:
@Before : 前置通知
@AfterReturnint : 后置通知
@AfterThrowing :异常通知
@After :最终通知
@Around :环绕通知
3.3 纯注解的配置
@EnableAspectJAutoProxy : 开启对AOP注解的支持
案例:转账
SpirngJunit-->accountService-->accountDao--->jdbcTemplate-->druid--->数据库
掌握:
1 AOP的作用
2 AOP的术语
3 必须会xml配置AOP
4 必须会半xml和半注解配置AOP
SpirngJunit-->accountService-->accountDao--->jdbcTemplate-->druid--->数据库
使用AOP的方式在不修改转账源码的基础上做事务增强(环绕通知来做)