首页 > 编程语言 >Java进阶篇——设计模式

Java进阶篇——设计模式

时间:2022-11-18 15:23:59浏览次数:43  
标签:Java invoke Object 代理 System 进阶篇 println 设计模式 public

设计模式

一、代理模式

使用代理类对真实对象进行代理,包括真实对象方法的调用、功能的扩展等。访问的时候也只能访问到代理对象,既保护了真实对象同时可以在原始对象上进行扩展。类似于中介在卖家和买家之间的角色。

代理模式的角色主要有:抽象角色、真实角色、代理角色

1.静态代理

以张三到二手平台售卖二手电脑为例,张三为真实角色,二手平台为代理角色

抽象角色:

public interface User {
    void sell();//购买方法
}

真实角色:

@Component
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserImpl implements User{

    private String name="张三";
    private String thing="二手电脑";

    @Override
    public void sell() {
        System.out.println(name+"要卖掉"+thing);
    }
}

代理角色:

@Component
public class UserProxy implements User {
    UserImpl user;

    @Override
    public void sell() {
        before();
        user.sell();
        after();
    }
    //扩展
    public void before(){
        System.out.println("包装了"+user.getThing());
    }
    public void after(){
        System.out.println("售后服务");
    }
}

测试:

@Component
public class StaticProxyTest {
    public static void main(String[] args) {
        new UserProxy(new UserImpl()).sell();
    }
}

看起来似乎很简单,只是加了一层代理类就实现了扩展功能,但实际上维护时非常困难的。如果用户此时新增了需求,要在平台上买东西。那么直接带来了大量的代码工作,效率很低。也就产生了动态代理。

2.动态代理

和静态代理不同的是,动态代理的代理类是spring为我们生成的。相当于mybatisplus和mybatis的区别。

代理类生成工具类

public class DynamicProxy {
    /*jdk动态代理
      代理类需要是接口实现类impl.getClass().getInterfaces(),接收代理实例也是用接口来接收
      通过反射Instance+拦截器Handler实现
      jdk自带的代理支持
    */
    public static Object jdkProxy(final Object impl){
        Object proxyInstance = Proxy.newProxyInstance(impl.getClass().getClassLoader(), impl.getClass()
                .getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object invoke=null;
                System.out.println("商品包装");
                invoke = method.invoke(impl, args);
                System.out.println("售后服务");
                return invoke;
            }
        });
        return proxyInstance;
    }

    /*CGlib动态代理
    通过对类继承来实现,无需接口实现
    第三方工具,基于ASM实现
    */
    public static Object CGlibProxy(final Object impl){
        Object proxyInstance = Enhancer.create(impl.getClass(), new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                Object invoke = null;
                System.out.println("商品包装");
                invoke = method.invoke(impl, objects);
                System.out.println("售后服务");
                return invoke;
            }
        });
        return proxyInstance;
    }

}

又或者可以实现对应的接口,以InvocationHandler举例

public class DynamicProxy implements InvocationHandler {
    private User user;
    
    public Object getProxyInstance(User user){
        this.user=user;
        return Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(),this);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object invoke = null;
        System.out.println("商品包装");
        invoke = method.invoke(user, args);
        System.out.println("售后服务");
        return invoke;
    }
}//实际使用中只需要调用getProxyInstance方法,丢入一个原始类即可

使用:

public class DynamicProxyTest {
    public static void main(String[] args) {
        UserImpl user = new UserImpl();
        User o = (User)DynamicProxy.jdkProxy(user);
        o.sell();
//        UserImpl o1 = (UserImpl)DynamicProxy.CGlibProxy(user);
//        o1.sell();
    }
}

3.Spring AOP

springaop便是动态代理实践的一个典例,不改变方法原有的代码,实现对方法功能的增强,使用aop之前,对aop相关的概念是一定要了解清楚的。

(1)aop相关概念

  • 通知(Advice): AOP 框架中的增强处理。通知描述了切面何时执行以及如何执行增强处理。
  • 接入点(join point): 连接点表示应用执行过程中能够插入切面的一个点,这个点可以是方法的调用、异常的抛出。在 Spring AOP 中,连接点总是方法的调用。
  • 切入点(PointCut): 可以插入增强处理的连接点。
  • 切面(Aspect): 切面是通知和切点的抽象集合,一般以类的形式呈现。
  • 织入(Weaving): 将增强处理添加到目标对象中,并创建一个被增强的对象,这个过程就是织入。
(2)springaop注解开发

由于目前来说,注解开发是最简单快捷的,这里只介绍注解开发,我们只需要知道底层是用动态代理实现的即可。

  • 创建切面类和通知

    只需要在类上添加@Aspect注解

    @Aspect
    public class MyAspect {
        public void before(){
            System.out.println("方法执行前");
        }
        public void after(){
            System.out.println("方法执行后");
        }
    }
    
  • 创建并注入切点

    @Aspect
    public class MyAspect {
        //表示将com.amlia.service包下的所有的类的所有方法(任何参数)定义为切点
        @Pointcut("execution(* com.amlia.service.*.*(..))")
        public void pointCut(){}
        @Before("pointCut()")
        public void before(){
            System.out.println("方法执行前");
        }
        //也可以直接在通知上面定义切点
        @After("execution(* com.amlia.service.*.*(..))")
        public void after(){
            System.out.println("方法执行后");
        }   
    }
    
  • 除了before和after类型的通知外,还有其他类型

    @Before:方法执行前通知

    @After:方法执行后通知

    @Around:方法环绕通知

    @AfterReturning:方法返回后通知

    @AfterThrowing:方法错误抛出之后

    可以测试他们的执行顺序:

(3)aop的应用
  • 打印日志(方法执行前后打印参数方法名返回值或者调用关系等信息)

    日志级别:

    • OFF 关闭日志
    • FATAL 较严重的问题,高于ERROR
    • ERROR 打印错误信息
    • WARN 打印告警信息
    • INFO 打印日常信息
    • DEBUG 打印调试信息
    • TRACE 打印追踪信息
    • ALL 打印所有信息
  • 性能检测(方法执行前和方法执行后分别进行时间截取求差值)

  • 事务控制(抛出错误后进行事务回滚)

  • 权限控制(方法执行前检测用户是否有权限)

标签:Java,invoke,Object,代理,System,进阶篇,println,设计模式,public
From: https://www.cnblogs.com/wtlbbdbk/p/16903347.html

相关文章

  • JavaWeb-06-Servlet
    6.Servlet6.1Servlet简介Servlet就是sun公司开发动态web的一门技术Sun公司在这些API中提供了一个接口叫作:Servlet,如果要开发一个Servlet程序,只需要完成两个步骤:编......
  • Java四种引用类型
    强引用默认的引用,任何对象被赋值即为强引用;强引用不会被GC回收。publicclassStrongReferenceUsage{@TestpublicvoidstringReference(){O......
  • Java阻塞队列
    ArrayBlockingQueue长度:固定(有界队列);锁类型:存取共用一个ReentrantLock锁,存取互斥;游标:两个index表示头和尾;阻塞条件:两个Condition标识空或者满,每次的存取操作都会唤醒对......
  • Java-14流Stream【创建一个简易for循环工具】
    Java-14流Stream构造简易的循环取代forIntStream类提供了一个range()方法,可以生成一个流————由int值组成的序列importstaticjava.util.stream.IntStream.*;/**......
  • 令人头疼的Javascript隐式&强制转换
    Javascript的隐式强制只是指Javascript试图将意外的值类型强制为预期的类型。因此,您可以在需要数字的地方传递一个字符串,在需要字符串的地方传递一个对象等,它会尝试将其......
  • Springboot项目java -jar 启动jar包参数详解
    Windows1、指定端口java-jarspringboot.jar--server.port=81812、指定配置文件java-jarspringboot.jar--spring.profiles.active=dev3、同时指定端口与配置文件ja......
  • Java反射与安全问题
    1.Java反射机制Java反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及......
  • 【java开发系列】—— JDOM创建、修改、删除、读取XML文件
    有很多中操作XML文件的方法,这里介绍一下JDOM的使用方法和技巧。 JDOM下载地址创建XML文档XML文件是一种典型的树形文件,每个文档元素都是一个document元素的子节点。......
  • Java并发中锁的种类
    锁的分类Java中锁分为以下几种:乐观锁、悲观锁共享锁、独享锁公平锁、非公平锁互斥锁、读写锁可重入、不可重入锁synchronized锁升级(无锁->偏向锁->轻量级锁......
  • Java内存马的学习总结
    1.前置知识JavaWeb三大组件ServletServlet是运行在Web服务器或应用服务器上的程序,它是作为来自HTTP客户端的请求和HTTP服务器上的数据库或应用程序之间的中间层......