spring的AOP思想

1.利用一个简单的静态的代理体会AOP思想(举例)

所谓的静态的代理就是在程序创建之前,代理类利用java代码实现
(1)首先创建一个接口:

public interface ProductService {

    public void biz1();
    public void biz2();
}

(2)创建一个目标的类,实现这个接口:

public class ProductTarget implements ProductService{
    @Override
    public void biz1() {
        System.out.println("事务biz1");
    }

    @Override
    public void biz2() {
        System.out.println("事务biz2");
    }
}

(3):编写一个代理类实现同样的接口:

public class ProductProxy  implements ProductService{

     private ProductAdvice advice = new ProductAdvice();
//获取一个通知类
    private
    static Method biz1;
    static Method biz2;
    static {
        try {
//            利用反射的机制,获取方法的信息
            biz1 = ProductService.class.getMethod("biz1");
            biz2 = ProductService.class.getMethod("biz2");
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }
    @Override
    public void biz1(){
        try {
            advice.invoke(this, biz1, new Object[]{});
        }catch (Throwable e){
            e.printStackTrace();
        }
    }

    @Override
    public void biz2() {
        try {
            advice.invoke(this,biz2,new Object[]{});
        }catch (Throwable e){
            e.printStackTrace();
        }
    }
}

(4)编写一个通知类:

public class ProductAdvice  implements InvocationHandler {

    private ProductTarget target = new ProductTarget();
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("事务开始");
        Object object = null;
        try {
           object = method.invoke(target,args);
            System.out.println("事务提交");
        }catch (Throwable e){
            e.printStackTrace();
            System.out.println("事务回滚");
        }
        System.out.println("事务结束");
        return object;
    }
}

分析:
让一个代理类和一个目标类(被代理的类)实现一个同样的接口,目的让调用者察觉不出是代理替换了原来的对象
代理类:
1:调用了通知类的invoke的方法
2:获取目标类的方法的对象和方法的实际的参数
通知类:
1:利用反射的技术调用目标类的方法,将事务的代码和重复的部分相互结合
2:实现一个InvocationHandler的接口,重写它的invoke的方法
参数1:Object proxy 代理类对象
参数2:Method method 方法的对象用来反射的技术来调用目标类的业务的方法
参数3:Object[] args 方法的参数

2.spring框架AOP思想的概述

spring的框架的另一个核心的思想为:AOP的思想
那么什么为AOP的思想?
AOP的思想就是面向切面的编程(Aspect Oriented Programming ):
具体的思想:
代理:Proxy
目标:Target 也是被代理的对象
通知:Advice 负责将重复的代码和业务的代码进行一个整合
切面:就是 等价于 切点(代表的是一种匹配的规)+通知(重复的代码和业务代码的整合)

3.动态的代理的技术

之前我们在程序应用之前将代理类用Java代码编写好的过程称之为静态的代理过程,但是代理类的编写的过程随着目标类的业务的方法变多的情况下,就会变得复杂,但是jdk我们提供了一个动态代理的技术,在应用程序运行的过程中,将代理类创建好。
举例:

 @Test
    public void test2() throws Throwable {
//        jdk的动态的代理的技术
//        获取一个动态的代理的对象
//       参数一:类加载器
//       参数二:接口的class的文件
//       参数三:通知类的对象
        ClassLoader loader = TestAop.class.getClassLoader();
        ProductService o = (ProductService)java.lang.reflect.Proxy.newProxyInstance(loader, new Class[]{ProductService.class}, new ProductAdvice());
        System.out.println(o.getClass());
        o.biz1();
    }

直接先生成.class的字节码的文件,然后加载到jvm上

4.spring 的AOP的使用

(1):pom.xml的文件的配置,添加相关的依赖:

<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>4.3.17.RELEASE</version>
        </dependency>

         <!--第三方 aop依赖 aspectJ-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.10</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.8.10</version>
        </dependency>

(2):编写相关的目标类和通知类,其中目标类实现一个接口
接口类

public interface UserService {

    public void biz1();

    public void biz2();

    public void biz3();

    public void biz4();
    public void biz4(int i);
}

目标类

public class UserTarget implements UserService {
    @Override
    public void biz1() {
        System.out.println("事务 biz1");
    }

    @Override
    public void biz2() {
        System.out.println("事务biz2");
    }

    @Override
    public void biz3() {
        System.out.println("事务biz3");
    }

    @Override
    public void biz4() {
        System.out.println("事务biz4");
    }

    @Override
    public void biz4(int i) {
        System.out.println("事务带参biz4 ");
    }
}

通知类,用来完成目标类业务的重复的代码与目标类的重复的代码进行整合
注解:
1:@aspect 意思是切面
2: @Around(“within(com.www.spring.service.UserTarget)”) 通知的类型:决定了通知的方法要与目标的哪些的方法进行结合

@Aspect
public class UserAdvice {

    @Around("within(com.www.spring.service.UserTarget)")
    public Object test1(ProceedingJoinPoint pjp){
        System.out.println("事务开始");
        Object object = null;
        try {
//            调用目标的方法
             object = pjp.proceed();
            System.out.println("提交事务");
        }catch (Throwable e){
            System.out.println("回滚事务");
            e.printStackTrace();
        }
        return  object;
    }
}

测试:

  static ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-AOP.xml");
    @Test
    public void test1(){
       
        UserService userService = context.getBean(UserService.class);
        userService.biz1();

    }

返回的对象是一个代理类的对象,这就体现了动态代理的技术

5.通知的类型和切点

5.1 通知类型

下面对主要的通知的类型进行举例:
(1)环绕的通知:@Around("") 环绕的通知 功能是最为齐全的一个方法 在通知方法的内部调用的是目标的方法
(2)前置通知: @Before("") 前置的通知 在目标方法调用之前就会调用通知的方法
(3)正常返回的通知:@AfterReturning ("") 正常返回的通知的方法,在目标方法正常调用完成之后就会调用正常返回的通知的方法
(4)结束通知:@After("") 就是在目标方法结束的时候(无论是正常的结束,还是异常的结束)都会被调用通知方法(在正常返回和异常返回的通知之前)
(5)异常通知:@AfterReturning("") 就是在目标的方法出现异常的时候会背带调用通知方法

5.2 切点

通俗的说就是一个匹配的规则:
有以下的几种的切点:
(1):within(“包名.类名”) :匹配的是这个类中的所有的方法
(2):execution(“权限修饰符.返回值类型.包名.类名.方法名(…)”)

  • 代表的是所有 (…) 匹配的是方法的参数
    (3):annotation(包名.注解名):根据方法上的注解来进行匹配,如果有注解就会匹配如果没有的话,就不会匹配
    注意:正常返回通知和异常的返回的通知针对的是目标类的目标的方法

6.常见的spring动态的创建代理的技术

spring有两种创建动态代理的技术:
(1)jdk的动态的代理的技术:
适用于目标类是实现了至少一个一个接口的情况之下
(2)cglib的动态的代理的技术:
如果目标类没有实现一个接口的情况下,就会适应cglib的技术来产生一个动态的代理
它的class的是:

class com.www.spring.service.UserTarget2$$EnhancerBySpringCGLIB$$bc3b1d3b

7.spring中AOP的过程的分析

当spring的容器启动的时候:
(1):spring的容器会先检查是否要要给容器的目标类创建代理
(2):检查切点的表达式,如果切点匹配到了目标类的话,就会给其创建代理
(3):在获取对象的时候,会检查是否有代理对象,如果有的话,就会优先创建代理的对象
(4):在获取到了代理对象的时候,会按照切点进行匹配进入多个通知类

Spring的专业名词

JoinPiont:连接点(可以被连接到的点,可以被拦截的点)
PiontCut:被真正拦截到的点
Advice:通知(目标方法执行的前后的执行的方法 )
Introduction:类层面的增强
Target:被增强的对象
Weaving:将通知应用到到Target的方法中的过程
Proxy:增强之后产生的代理
Aspect:多个通知和多个切入点的组合

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值