寒假学习第9篇
### 5.6 Spring AOP基于XML方式实现(了解)
  1. 准备工作
加入依赖
和基于注解的 AOP 时一样。
准备代码
      把测试基于注解功能时的Java类复制到新module中,去除所有注解。
  2. 配置Spring配置文件
```XML
<!-- 配置目标类的bean -->
<bean id="calculatorPure" class="com.atguigu.aop.imp.CalculatorPureImpl"/>
    
<!-- 配置切面类的bean -->
<bean id="logAspect" class="com.atguigu.aop.aspect.LogAspect"/>
    
<!-- 配置AOP -->
<aop:config>
    
    <!-- 配置切入点表达式 -->
    <aop:pointcut id="logPointCut" expression="execution(* *..*.*(..))"/>
    
    <!-- aop:aspect标签:配置切面 -->
    <!-- ref属性:关联切面类的bean -->
    <aop:aspect ref="logAspect">
        <!-- aop:before标签:配置前置通知 -->
        <!-- method属性:指定前置通知的方法名 -->
        <!-- pointcut-ref属性:引用切入点表达式 -->
        <aop:before method="printLogBeforeCore" pointcut-ref="logPointCut"/>
    
        <!-- aop:after-returning标签:配置返回通知 -->
        <!-- returning属性:指定通知方法中用来接收目标方法返回值的参数名 -->
        <aop:after-returning
                method="printLogAfterCoreSuccess"
                pointcut-ref="logPointCut"
                returning="targetMethodReturnValue"/>
    
        <!-- aop:after-throwing标签:配置异常通知 -->
        <!-- throwing属性:指定通知方法中用来接收目标方法抛出异常的异常对象的参数名 -->
        <aop:after-throwing
                method="printLogAfterCoreException"
                pointcut-ref="logPointCut"
                throwing="targetMethodException"/>
    
        <!-- aop:after标签:配置后置通知 -->
        <aop:after method="printLogCoreFinallyEnd" pointcut-ref="logPointCut"/>
    
        <!-- aop:around标签:配置环绕通知 -->
        <!--<aop:around method="……" pointcut-ref="logPointCut"/>-->
    </aop:aspect>
    
</aop:config>
```
  3. 测试
```Java
@SpringJUnitConfig(locations = "classpath:spring-aop.xml")
public class AopTest {
    @Autowired
    private Calculator calculator;
    @Test
    public void testCalculator(){
        System.out.println(calculator);
        calculator.add(1,1);
    }
}
```
### 5.7 Spring AOP对获取Bean的影响理解
  #### 5.7.1 根据类型装配 bean
    1. 情景一
        - bean 对应的类没有实现任何接口
        - 根据 bean 本身的类型获取 bean
            - 测试:IOC容器中同类型的 bean 只有一个
                正常获取到 IOC 容器中的那个 bean 对象
            - 测试:IOC 容器中同类型的 bean 有多个
                会抛出 NoUniqueBeanDefinitionException 异常,表示 IOC 容器中这个类型的 bean 有多个
    2. 情景二
        - bean 对应的类实现了接口,这个接口也只有这一个实现类
            - 测试:根据接口类型获取 bean
            - 测试:根据类获取 bean
            - 结论:上面两种情况其实都能够正常获取到 bean,而且是同一个对象
    3. 情景三
        - 声明一个接口
        - 接口有多个实现类
        - 接口所有实现类都放入 IOC 容器
            - 测试:根据接口类型获取 bean
                会抛出 NoUniqueBeanDefinitionException 异常,表示 IOC 容器中这个类型的 bean 有多个
            - 测试:根据类获取bean
                正常
    4. 情景四
        - 声明一个接口
        - 接口有一个实现类
        - 创建一个切面类,对上面接口的实现类应用通知
            - 测试:根据接口类型获取bean
                正常
            - 测试:根据类获取bean
无法获取
原因分析:
        - 应用了切面后,真正放在IOC容器中的是代理类的对象
        - 目标类并没有被放到IOC容器中,所以根据目标类的类型从IOC容器中是找不到的
    5. 情景五
        - 声明一个类
        - 创建一个切面类,对上面的类应用通知
            - 测试:根据类获取 bean,能获取到
debug查看实际类型:
#### 5.7.2 使用总结
对实现了接口的类应用切面
对没实现接口的类应用切面new
**如果使用AOP技术,目标类有接口,必须使用接口类型接收IoC容器中代理组件!**
 
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号