B057-spring增强 依赖注入 AOP 代理模式 创建Bean

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

目录

AOP

概念

在这里插入图片描述
事务管理比如可以抽取try catch的重复代码
日志监控比如业务逻辑前后打印关于当前订单数量的日志了解业务做了什么
性能监控比如业务前后打印时间相减可查看业务跑完所需时间

代理模式引出

在这里插入图片描述
用aop实现扩展功能
aop用代理模式实现但是代理模式里的扩展功能还是需要我们自己写

静态代理相当于一个中介只代理一个固定的房东的房源基本不用
动态代理默认没有使用的时候动态生成

AOP以上大方向
SpringAOPAOP的spring实现方式用动态代理方式实现。它的实现方式又有两种jdkCGLIBspring自动选择用其中哪种方式代理类自动生成也不用管有接口的时候默认使用jdk没有的时候用cglib(第三方jar包)现在一般service都有接口

AOP实现方式

xml方式实现

1.编写TxManager用来提供业务逻辑外的扩展功能 - 如事务管理

/*我们自己的扩展功能*/
public class TxManager {

    public void open (){
        System.out.println("开启事务");
    }

    public void commit (){
        System.out.println("提交事务");
    }

    public void rollback(Throwable e){
        e.printStackTrace();//处理异常
        System.out.println("回滚事务");
    }

    public void close(){
    System.out.println("关闭事务");
    }

    public void around(ProceedingJoinPoint point){
        try {
            open();
            point.proceed();//执行真正的业务
            commit();
        } catch (Throwable e) {
            e.printStackTrace();
            rollback(e);
        } finally {
            close();
        }
    }
}

2.准备xmlAOP环境在Spring配置文件中引入头支持以支持aop标签

SpringTest-Context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

3.配置的三要素
何时如在业务的执行前、后、catch
何地指的是在哪一个方法
做什么执行我们自定义扩展业务类的方法

面向切面编程面向扩展功能编程
在这里插入图片描述
其他
spring通过动态代理实现aop配置aop后只能注入接口通过接口找到被引用的代理类Spring容器中就只有代理类没有实现类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration//回到当前类的包下 查找当前类名-Context.xml的配置文件
public class SpringTest {

    @Autowired
    IUserService userService;

    @Test
    public void testUser(){
        System.out.println(userService.getClass());
    }
}

SpringTest-Context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="userService" class="cn.itsource._03aopxml.service.impl.UserServiceImpl"/>
    <bean id="departmentService" class="cn.itsource._03aopxml.service.impl.DepartmentServiceImpl"/>

    <!--将扩展功能交给Spring容器管理方便AOP使用-->
    <bean id="txManager" class="cn.itsource._03aopxml.TxManager"/>
    <!--SpringAOP的核心配置-->
    <aop:config>
        <!--配置切点  配置何地 ==在哪一个方法执行
            expression表达式  通过表达式我们找在哪一个方法执行
            第一个*任意返回值
            I*Service:所有以I开头 Service结尾的类里面的所有方法都加上事物
            第三个*任意方法
            save(..):任意参数
        -->
        <!--execution(* cn.itsource._03aopxml.service.impl.UserServiceImpl.save(..))
            execution(* cn.itsource._03aopxml.service.impl.UserServiceImpl.*(..))-->
        <aop:pointcut id="txPoint" expression="execution(* cn.itsource._03aopxml.service.I*Service.*(..))"/>
        <!--配置切面   -->
        <aop:aspect ref="txManager">
            <!--配置前置通知 配置何时做什么-->
            <!--<aop:before method="open" pointcut-ref="txPoint"/>-->
            <!--配置后置通知-->
            <!--<aop:after-returning method="commit" pointcut-ref="txPoint"/>-->
            <!--配置异常通知-->
            <!--<aop:after-throwing method="rollback" pointcut-ref="txPoint" throwing="e"/>-->
            <!--配置最终通知-->
            <!--<aop:after method="close" pointcut-ref="txPoint"/>-->
            <!--配置环绕通知  环绕通知一行顶上面四行-->
            <aop:around method="around" pointcut-ref="txPoint"/>
        </aop:aspect>
    </aop:config>
</beans>

测试

详细见工程代码

注解方式实现

A 引入容器扫描头 Spring AOP

SpringTest-Context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!--开启Spring注解扫描-->
    <context:component-scan base-package="cn.itsource._04aopanno"/>

    <!--开启SpringAOP 注解扫描-->
    <aop:aspectj-autoproxy/>

</beans>

后面的几步都是在TxManager中完成
B 将扩展业务交给容器管理 @Component
C 申明pointcut@Pointcut需要提供一个空方法
D 配置各种通知
只用@Around环绕通知其他四种通知不能确定执行顺序

/*我们自己的扩展功能*/
@Component //组件 把当前类交给Spring容器管理
@Aspect //== <aop:aspect ref="txManager"> 配置切面
public class TxManager {

    //配置切点  == <aop:pointcut id="txPoint"
    @Pointcut("execution(* cn.itsource._04aopanno.service.I*Service.*(..))")
    public void  txPoint(){
        /*这个方法指明在业务类中的每个方法*/
    }

    /*配置前置通知*/
    /*@Before("txPoint()")*/
    public void open (){
        System.out.println("开启事物");
    }

    /*@AfterReturning("txPoint()")*/
    public void commit (){
        System.out.println("提交事物");
    }

    /*@AfterThrowing(value = "txPoint()", throwing = "e")*/
    public void rollback(Throwable e){
        e.printStackTrace();//处理异常
        System.out.println("回滚事务");
    }

    /*@After("txPoint()")*/
    public void close(){
    System.out.println("关闭事物");
    }

    @Around("txPoint()")
    public void around(ProceedingJoinPoint point){
        try {
            open();
            point.proceed();//执行真正的业务
            commit();
        } catch (Throwable e) {
            e.printStackTrace();
            rollback(e);
        } finally {
            close();
        }
    }
}

测试

详细见工程代码

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: Spring