Spring框架(代理模式)--4

目录

1. 代理模式

1.1 创建项目

1.1.1创建项目

1.1.2 完成入门代码测试

1.1.3 编辑UserService

1.1.4 业务层如何控制事务

1.1.4 业务代码-问题说明

1.2 代理机制

1.2.1 代理模式特点

1.2.1 代理特点

1.3 动态代理-JDK模式

1.3.1 JDK代理的说明

1.3.2 编辑代理类 

 1.3.3 编辑测试类

1.4 动态代理-JDK模式案例

1.4.1 编辑代理对象

 1.4.2 编辑测试方法

1.5 动态代理-CGLIB代理

1.5.1 CGLIB说明

1.5.2 CGLIB代理模式

1 .5.3 CGLIB代理测试类

 1.6 关于JDK代理和CGlib代理总结(高程/架构)!!!

2. Spring AOP介绍

2.1 创建项目

2.1.1 基本结构

 2.1.2 层级代码结构

2.1.3 层级代码结构 

2.2 AOP

2.2.1 AOP介绍

2.2.2 AOP 入门案例

2.3 常见通知类型


1. 代理模式



1.1 创建项目



1.1.1创建项目

在这里插入图片描述

1.1.2 完成入门代码测试

在这里插入图片描述

1.1.3 编辑UserService


1.1.3.1 编辑Service接口

package com.jt.service;

public interface UserService {

    void addUser();
}

 1.1.3.2 编辑ServiceImpl实现类

package com.jt.service;

import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService{

    @Override
    public void addUser() {
        System.out.println("新增用户");
    }
}

1.1.4 业务层如何控制事务

事务: 可以保证数据的/原子性/一致性/持久性/隔离性.
说明: 业务层操作时,需要考虑数据库的事务.代码结构如下:

package com.jt.service;

import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService{

    @Override
    public void addUser() {
        try {
            System.out.println("开启数据库事务");
            System.out.println("新增用户");
            int a = 1/0;
            System.out.println("提交数据库事务");
        }catch (Exception e){
            System.out.println("事务回滚");
        }
    }
}

1.1.4 业务代码-问题说明

  1. 如果有多个方法,则每个方法都需要控制事务. 代码重复率高.
  2. 业务层service,应该只处理业务,不要和事务代码耦合在一起.否则扩展性不好,耦合性高.

如何解决: 采用代理机制解决.

1.2 代理机制



1.2.1 代理模式特点

说明: 一般采用代理模式,主要的目的就是为了解耦.将公共的通用的方法(功能/业务)放到代理对象中. 由业务层专注于业务执行即可.

1.2.1 代理特点

  1. 为什么使用代理? 因为自己不方便(没有资源)
  2. 代理的作用? 代理要解决(扩展)某些实际问题.
  3. 用户最终执行目标方法!!!

在这里插入图片描述

1.3 动态代理-JDK模式



1.3.1 JDK代理的说明

  1. JDK代理模式是java原生提供的API,无需导包
  2. JDK代理要求: 被代理者必须 要么是接口,要么实现接口
  3. 灵活: 代理对象应该看起来和被代理者 一模一样!!! (方法相同)

1.3.2 编辑代理类 

package com.jt.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class JDKProxy {

    //传入target目标对象获取代理对象的
    //利用代理对象 实现方法的扩展
    public static Object getProxy(Object target){
        //1.获取类加载器
        ClassLoader classLoader = target.getClass().getClassLoader();
        //2.获取接口数组类型
        Class[] interfaces = target.getClass().getInterfaces();
        //3.代理对象执行方法时的回调方法(代理对象调用方法时,执行InvocationHandler)
        return Proxy.newProxyInstance(classLoader,interfaces,invocationHandler(target));
    }

    //要求必须传递目标对象
    public static InvocationHandler invocationHandler(Object target){
       return new InvocationHandler() {
           @Override
           public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
               System.out.println("事务开启");
               //获取目标方法的返回值
               Object result = method.invoke(target,args);
               System.out.println("事务提交");
               return result;
           }
       };
    }
}

 1.3.3 编辑测试类

package com.jt;

import com.jt.config.SpringConfig;
import com.jt.proxy.JDKProxy;
import com.jt.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestSpring {

    @Test
    public void demo1(){
        ApplicationContext context =
                new AnnotationConfigApplicationContext(SpringConfig.class);
        //获取目标对象
        UserService userService = context.getBean(UserService.class);
        //userService.addUser();
        //获取代理对象
        UserService proxy = (UserService) JDKProxy.getProxy(userService);
        //代理对象执行方法, 调用invoke方法
        proxy.addUser();
    }
}

1.4 动态代理-JDK模式案例

需求: 要求大家计算addUser()方法的运行时间? 要求采用动态代理的方式完成.



1.4.1 编辑代理对象

 public static Object getTimePorxy(Object target){
        ClassLoader classLoader = target.getClass().getClassLoader();
        Class[] interfaces = target.getClass().getInterfaces();
        return Proxy.newProxyInstance(classLoader,interfaces,invocationHandlerTime(target));
    }

    //要求必须传递目标对象
    public static InvocationHandler invocationHandlerTime(Object target){
        return new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //开始时间
                long startTime = System.currentTimeMillis();
                //让目标方法执行 结果
                Object result = method.invoke(target,args);
                long endTime = System.currentTimeMillis();
                System.out.println("耗时:"+(endTime - startTime));
                return result;
            }
        };
    }

 1.4.2 编辑测试方法

package com.jt;

import com.jt.config.SpringConfig;
import com.jt.proxy.JDKProxy;
import com.jt.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestSpring {

    @Test
    public void demo1(){
        ApplicationContext context =
                new AnnotationConfigApplicationContext(SpringConfig.class);
        //获取目标对象
        UserService userService = context.getBean(UserService.class);
        System.out.println(userService.getClass());
        //userService.addUser();
        //获取代理对象
        UserService proxy = (UserService) JDKProxy.getTimePorxy(userService);
        System.out.println(proxy.getClass());
        //代理对象执行方法, 调用invoke方法
        proxy.addUser();
    }
}

1.5 动态代理-CGLIB代理



1.5.1 CGLIB说明

jdk代理: 要求必须有/实现接口. 如果没有接口,则JDK代理不能正常执行.
cglib代理: 要求被代理者有无接口都可以. 代理对象是目标对象的子类 重写子类方法



1.5.2 CGLIB代理模式

package com.jt.proxy;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CGlibProxy {

    public static Object getProxy(Object target){
        //1.创建增强器对象
        Enhancer enhancer = new Enhancer();
        //2.设定父级 目标对象
        enhancer.setSuperclass(target.getClass());
        //3.定义回调方法 代理对象执行目标方法时调用
        enhancer.setCallback(getMethodInterceptor(target));
        //4.创建代理对象
        return enhancer.create();
    }
    //需要传递target目标对象
    public static MethodInterceptor getMethodInterceptor(Object target){
        return new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                System.out.println("事务开始");
                //执行目标方法
                Object result = method.invoke(target,args);
                System.out.println("事务提交");
                return result;
            }
        };
    }
}

1 .5.3 CGLIB代理测试类

@Test
    public void demo2(){
        ApplicationContext context =
                new AnnotationConfigApplicationContext(SpringConfig.class);
        //获取目标对象
        UserService userService = context.getBean(UserService.class);
        UserService proxy = (UserService) CGlibProxy.getProxy(userService);
        System.out.println(proxy.getClass());
        proxy.addUser();
    }

 在这里插入图片描述

 1.6 关于JDK代理和CGlib代理总结(高程/架构)!!!

1. JDK要求必须有或者实现接口, cglib有无接口都可以创建代理对象.代理对象是目标对象的子类
2. JDK代理工具API: Proxy.newProxyInstance(类加载器,接口数组,invocationHandler接口)
3. CGlib代理工具API: Enhancer 增强器对象 获取代理对象 enhancer.create(); 回调接口
MethodInterceptor接口
4. JDK中执行目标方法
-method.invoke(target,args);
CGlib中执行目标方法
-method.invoke(target,args);
 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

#空城

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值