Spring基础入门AOP

AOP简介

1.什么是AOP ? 它有什么用?

AOP(Aspect Oriented Programming,面向切面编程), 可以说是OOP(Object Oriented Programing,面向对象编程)的补充和完善。在不改动源码的前提下,对原有的功能进行扩展 | 升级

2.AOP的底层原理是什么?

在JAVA的世界里,能够不改代码而又能进行扩展代码的,不多,常见的有装饰者模式,代理模式(静态代理,动态代理),而AOP的底层使用的是动态代理,因为使用静态代理 | 装饰者模式 需要提供一个实实在在类,而使用动态代理,只需要一个被装饰对象,或对象字节码对象即可

3.代理回顾,静态代理方式
这里写图片描述

3.代理回顾,动态代理实现方式
这里写图片描述

画的有点丑,别介意

4.基于JDK方式代码

//创建一个接口   JDK方式需要实现接口,如果类没有实现接口,那么只能使用cglib方式
public interface A {

    void run();
    void eat();
}
//创建一个实体类   实现接口
public class People implemts A{

    public void eat(){
        System.out.println("吃");   
    }
    public void run(){
        System.out.println("跑");
    }
}
public class Jdk {

    @Test
    public void Test_01(){
        A people = new People();  //创建实体类对象

//        使用动态代理
        Class clazz = people.getClass();
        //Proxy.newProxyInstance()需要的参数 
        //1.类加载器  2.目标类实现的接口,也就是People实现的接口  3.一个new InvocationHandler()的回调函数

        //获取代理对象
      A a = (A) Proxy.newProxyInstance(this.getClass().getClassLoader(), clazz.getInterfaces(), new InvocationHandler() {
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //加强睡的方法
                if ("eat".equals(method.getName())) {
                    System.out.println("加餐啦!");
                }


                return method.invoke(people,args);
            }
        });

        proxy.eat();
    }

}

运行结果如下
这里写图片描述


5.基于Cglib方式代码

主要针对没有实现接口的类,底层通过创建另一个子类作为代理类

//创建一个目标类,不实现接口
public class Anli {

    public void eat(){
        System.out.println("开始吃");
    }

    public void run(){
        System.out.println("开始跑");
    }
}

创建一个测试类

public class Cglib {

    @Test
    public void Test_01(){
        //创建目标类的真实对象,
       final Anli anli = new Anli();

       //创建一个代理对象
        Enhancer enhancer = new Enhancer();  //这不是代理对象,是创建代理对象的模板,可以理解为代理对象工厂

        enhancer.setSuperclass(anli.getClass());

        enhancer.setCallback(new MethodInterceptor() {
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
              //加强吃的方法
                if ("eat".equals(method.getName())) {
                    System.out.println("再一次加餐啦");
                }

                return method.invoke(anli,objects);
            }
        });

        //创建代理类
        Anli a = (Anli)enhancer.create();

        a.eat();
    }
}

运行结果如下
这里写图片描述

总结 : 被代理类如果实现了接口就使用JDK的方式,如果没有实现,就是用Cglib方式,开发中通常会使用JDK的方式,开发中都是使用接口来定义规范的.

6.回归正题,我们开始讲AOP

讲AOP之前,我们需要了解AOP的术语,

  • 连接点
  • 切入点
  • 切面

话不多说,直接上图
这里写图片描述

了解完AOP术语,那么我们就开始实际操作

1.导入spring需要的jar包,和日志包(如果没有的话,可以在我上传资源里面下载,注意,jar包只用导入一部分)
导入jar包如下

  • 五个核心jar包
    spring-beans-xxx.jar
    spring-context-xxx.jar
    spring-context.xxx.jar
    spring-core-xxx.jar
    spring-expression-xxx.jar
  • 日志jar包
    jcl-over-slf4j-xxx.jar
    log4j-xxx.jar
    slf44j-api-xxx.jar
    slf4j-log4j-xxx.jar
    需要注意的是,导入日志jar包后,需要提供一个log4j.properties文件
  • 导入aop需要的jar包
    spring-aop-xxx.jar
    spring-aspects-xxx.jar
    面向切面过程中Spring AOP是遵循AOP联盟规范实现的,所以需要AOP联盟的接口包
    aoplliance-xx.jar
    接口包依赖aspectJweaver-xxx.jar
    如果没有jar包的话,可以在我的资源里面找

log4j.properties文件内容如下

##\u8BBE\u7F6E\u65E5\u5FD7\u8BB0\u5F55\u5230\u63A7\u5236\u53F0\u7684\u65B9\u5F0F
log4j.appender.s=org.apache.log4j.ConsoleAppender
log4j.appender.s.Target=System.err
log4j.appender.s.layout=org.apache.log4j.PatternLayout
log4j.appender.s.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n

##\u8BBE\u7F6E\u65E5\u5FD7\u8BB0\u5F55\u5230\u6587\u4EF6\u7684\u65B9\u5F0F
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n

##\u65E5\u5FD7\u8F93\u51FA\u7684\u7EA7\u522B\uFF0C\u4EE5\u53CA\u914D\u7F6E\u8BB0\u5F55\u65B9\u6848
log4j.rootLogger=info, s, file 

2.导入applicationContext.xml配置所需要的约束 (aop约束)
spring-framework-4.2.9.RELEASE\docs\spring-framework-reference\html\xsd-configuration.html里面搜索aop就行

spring-framework-4.2.9.RELEASE是在spring官网下载的文件夹名
html索搜快捷键 ctrl+shift +f
复制约束,粘贴到xml即可

3.编写xml

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

    <bean id="Pipixia" class="cn.itcast.aop.Pipixia"/>
    <bean id="People" class="cn.itcast.aop.People"/>


    <aop:config >

        <!-- 切入点  到底哪些方法要被扩展
        execution(* com.xyz.myapp.service..(..))
        execution: 固定写法
        第一个* : 任意返回值
        com.xyz.myapp.service : 具体包
        第二个* : 包下的所有类
        第三个* : 类中的所有方法
        (..) : 方法的任意参数
    -->
<!--创建一个切入点-->
        <aop:pointcut id="point" expression="execution(* cn.itcast.aop.Pipixia.*(..))"/>

        <!--创建一个切面  ,ref是提供扩展方法的类-->
        <aop:aspect ref="People">
                     <!--提供People类的eat方法,before是增强位置-->
           <aop:before method="eat" pointcut-ref="point" />
        </aop:aspect>
    </aop:config>
</beans>

AOP增加介绍

<aop:config>
    <!-- us  === saveUser
        ps  === saveProduct
        os  ===saveOrder -->
    <aop:pointcut expression="execution(* com.itcast.*.*.eat*(..))" id="aa"/>

    <aop:aspect ref="People">

        <!-- 前置增强,People类eat方法会在执行itcast包下所有类的方法前执行,只要是itcast包下的方法,执行前都会执行一遍People的方法,出异常不知晓 -->
        <!-- <aop:before method="eat" pointcut-ref="aa" /> -->

        <!-- 最终增强  不管有没有异常都执行-->
        <!-- <aop:after method="eat" pointcut-ref="aa" /> -->

        <!-- 环绕增强 -->
        <!-- <aop:before method="eat" pointcut-ref="aa" />
        <aop:after method="eat" pointcut-ref="aa" /> -->
        <!--环绕增强,被增强方法执行前后都是执行eat方法,不过需要额外配置-->
        <!-- <aop:around method="around" pointcut-ref="aa"/> -->

        <!-- 后置增强,被增强方法执行完后会执行一遍 People类的eat方法-->
        <!-- <aop:after-returning method="eat" pointcut-ref="aa"/> -->

        <!-- 异常增强,被增强方法出了异常才会增强执行eat方法 -->
        <aop:after-throwing method="eat" pointcut-ref="aa"/>
    </aop:aspect>
  </aop:config>

由于时间问题,就不演示了
就值演示一个before前置增强
编写一个测试类

//使用spring提供的测试方法,使用需要导入test的jar包 
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo_02 {

    @Resource
    private Pipixia p;

    @Test
    public  void demo_01(){

        p.eat();

    }
}

执行结果如下
这里写图片描述

它先执行了People的eat方法,
这里写图片描述
然后再执行了Pipixia的eat方法
这里写图片描述

以上就是AOP简单入门,下次我们会讲IOC,DI注解写法,有问题评论留言

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值