Java面试知识点(全)-spring面试知识点一

news2024/11/25 1:05:59

Java面试知识点(全)
导航: https://nanxiang.blog.csdn.net/article/details/130640392
注:随时更新

Spring原理

Spring ioc概念:控制权由对象本身转向容器;由容器根据配置文件去创建实例并创建各个实例之间的依赖关系。核心:beanFactory;在Spring中,beanFactory创建的各个实例称作bean,其通过java反射实现

Spring还有一个核心就是AOP这个就是面向切面编程,可以为某一类对象 进行监督和控制(指定类或者通用)从而达到对一个模块扩充的功能。这些都是通过配置类达到的。AOP其实现的原理为动态代理(面向接口使用JDK的,面向类使用cglib),
Spring目的:就是让对象与对象(模块与模块)之间的关系没有通过代码来关联,都是通过配置类说明管理的(Spring根据这些配置 内部通过反射去动态的组装对象)
要记住:Spring是一个容器,凡是在容器里的对象才会有Spring所提供的这些服务和功能。

Spring里用的最经典的一个设计模式就是:模板方法模式。(这里我都不介绍了,是一个很常用的设计模式),Spring里的配置是很多的,很难都记住,但是Spring里的精华也无非就是以上的两点,把以上两点跟理解了 也就基本上掌握了Spring.

Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式,组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下:
核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转 (IOC)模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。
Spring 上下文:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。
Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。
Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。
Spring ORM:Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。
Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。

Spring 内部工作机制

Spring的AbstractApplicationContext 是ApplicationContect的抽象实现类,该抽象实现类的refresh()方法定义了Spring容器再加载配置文件后的各项处理过程。

  • 1、初始化BeanFactory
    初始化BeanFactory:根据配置文件实例化BeanFactory,在obtainFreshBeanFactory()方法中,首先调用refreshBeanFactory()方法刷新BeanFactory,然后调用getBeanFactory()方法获取BeanFactory,这两个方法都是由具体子类实现。在这一步里,Spring将配置文件的信息装入容器的Bean定义注册表(BeanDefinitionRegistry)中,但是此时Bean还没有初始化;
  • 2、调用工厂后处理器
    根据反射机制从BeanDefinitionRegistry中找出所有实现了BeanFactoryPostProcessor接口的Bean,并调用其postProcessBeanFactory()接口方法;
  • 3、注册Bean后处理器
    根据反射机制从BeanDefintionRegistry中找出所有实现了BeanPostProcessor接口的Bean,并将它们注册到容器Bean后处理的注册表;
  • 4、初始化消息源
    initMessageSource()初始化容器的国际化消息资源;
  • 5、初始化应用上下文事件广播器;
  • 6、初始化其他特殊的Bean
    这是一个钩子方法。子类可以借助这个方法执行一些特殊的操作,如AbstractRefreshableWebApplicationContext就使用该方法执行初始化ThemeSource的操作;
  • 7、注册事件监听器;
  • 8、初始化所有单实例的Bean,使用懒加载模式的Bean除外:
    初始化Bean后,将它们放入Spring容器的缓存池中;
  • 9、初始化上下文刷新事件
    创建上下文刷新事件,事件广播器负责将这些事件广播到每个注册的事件监听器中。

Spring ioc 原理

所谓控制反转,就是把原先我们代码里面需要实现的对象创建、依赖的代码,反转给容器来帮忙实现。那么必然的我们需要创建一个容器,同时需要一种描述来让容器知道需要创建的对象与对象的关系。核心为BeanFactory,实现机制为java反射

Bean生命周期

在这里插入图片描述

体过程如下:
1.当调用者通过getBean(beanName)向容器请求某一个Bean时,如果容器注册了org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor接口,则在实例化Bean之前,将调用接口的postProcessBeforeInstantiation()方法;
2.根据配置情况调用Bean的构造函数或工厂方法实例化Bean;
3.如果容器注册了InstantiationAwareBeanPostProcessor接口,那么实例化Bean之后,调用该接口的postProcessAfterInstantiation()方法,可在这里对已经实例化的对象进行一些"梳妆打扮";
4.如果Bean配置了属性信息,那么容器在这一步着手将配置值设置到Bean对引发的属性中,不过在设置每个属性之前将先调用InstantiationAwareBeanPostProcessor接口的postProcessPorpertyValues()方法;
5.调用Bean的属性设置方法设置属性值;
6.如果Bean实现了org.springframework.beans.factory.BeanBaneAware接口则将调用setBeanName()接口方法,将配置文件中该Bean对应的名称设置到Bean中;
7.如果Bean实现了org.springframework.beans.factory.BeanFactoryAware接口,则将调用setBeanFactory()接口方法,将BeanFactory容器实例设置到Bean中;
8.如果BeanFactory装配了org.springframework.beans.factory.config.BeanPostProcessor后处理器,则将调用BeanPostProcessor的Object postProcesBeforeInitializaton(Object bean,String beanName)接口方法对Bean进行加工操作。其中,入参bean是当前正在处理的Bean,而beanName是当前的配置名,返回的对象为加工处理后的Bean。用户可以使用该方法对某些Bean进行特殊的处理,甚至改变Bean的行为。BeanPostProcessor在Spring框架中占有重要的地位,为容器提供对Bean进行后续加工处理的切入点,Spring容器所提供的各种"神奇功能"(AOP、动态代理等)都是通过BeanPostProcessor实施的;
9.如果Bean实现了InitializingBean接口,则将调用接口的afterPropertiesSet()方法;
10.如果配置文件中通过init-method属性定义了初始化方法,则将执行这个方法;
11.BeanPostProcessor后处理器定义了两个方法:其一是postProcessBeforeInitialization(),在第8步调用;其二是Object postProcessAfterInitialization(Object bean,String beanName),这个方法在此时调用,容器将再次获取对Bean进行加工处理的机会;
12.如果配置文件中指定Bean的作用范围为scope=“prototype”,则将Bean返回给调用者,调用者负责Bean后续生命的管理,Spring不在管理这个Bean的生命周期;如果将作用范围设置为scope=“singleton”,则将Bean放入Spring IoC容器的缓存池中,并将Bean引用返回调用者,Spring继续对这些Bean进行后续的生命管理;
13.对于scope="singleton"的Bean(默认情况),当容器关闭时,将触发Spring对Bean后续生命周期的管理工作。如果Bean实现了DisposableBean接口,则将调用接口的destory()方法,可以在此编写释放资源、记录日志等操作;
14.对于scope="singleton"的Bean,如果通过配置文件中的destory-method属性指定了Bean的销毁方法,那么Spring将执行Bean的这个方法,完成Bean资源的释放等操作。

Java反射

实现原理:
Class反射对象描述类语义结构,可以从Class对象中获取构造函数、成员变量、方法类等类元素的反射对象,并以编程的方式通过这些反射对象对目标类对象进行操作。这些反射对象类在java.reflect包中定义,下面是最主要的三个反射类:

Constructor:类的构造函数反射类,通过Class#getConstructors()方法可以获得类的所有构造函数反射对象数组。在JDK5.0中,还可以通过getConstructor(Class… parameterTypes)获取拥有特定入参的构造函数反射对象。Constructor的一个主要方法是newInstance(Object[] initargs),通过该方法可以创建一个对象类的实例,相当于new关键字。在JDK5.0中该方法演化为更为灵活的形式:newInstance (Object… initargs)。

Method:类方法的反射类,通过Class#getDeclaredMethods()方法可以获取类的所有方法反射类对象数组Method[]。在JDK5.0中可以通过getDeclaredMethod(String name, Class… parameterTypes)获取特定签名的方法,name为方法名;Class…为方法入参类型列表。Method最主要的方法是invoke(Object obj, Object[] args),obj表示操作的目标对象;args为方法入参,代码清单3 10③处演示了这个反射类的使用方法。在JDK 5.0中,该方法的形式调整为invoke(Object obj, Object… args)。此外,Method还有很多用于获取类方法更多信息的方法:

1)Class getReturnType():获取方法的返回值类型;
2)Class[] getParameterTypes():获取方法的入参类型数组;
3)Class[] getExceptionTypes():获取方法的异常类型数组;
4)Annotation[][] getParameterAnnotations():获取方法的注解信息,JDK 5.0中的新方法;

Field:类的成员变量的反射类,通过Class#getDeclaredFields()方法可以获取类的成员变量反射对象数组,通过Class#getDeclaredField(String name)则可获取某个特定名称的成员变量反射对象。Field类最主要的方法是set(Object obj, Object value),obj表示操作的目标对象,通过value为目标对象的成员变量设置值。如果成员变量为基础类型,用户可以使用Field类中提供的带类型名的值设置方法,如setBoolean(Object obj, boolean value)、setInt(Object obj, int value)等。

此外,Java还为包提供了Package反射类,在JDK 5.0中还为注解提供了AnnotatedElement反射类。总之,Java的反射体系保证了可以通过程序化的方式访问目标类中所有的元素,对于private或protected的成员变量和方法,只要JVM的安全机制允许,也可以通过反射进行调用,请看下面的例子:

代码清单3-12 PrivateCarReflect

publicclassPrivateCar{
//①private成员变量:使用传统的类实例调用方式,只能在本类中访问
privateStringcolor;
//②protected方法:使用传统的类实例调用方式,只能在子类和本包中访问
protectedvoiddrive(){

System.out.println("driveprivatecar!thecoloris:"+color);
}
}

//color变量和drive()方法都是私有的,通过类实例变量无法在外部访问私有变量、调用私有方法的,但通过反射机制却可以绕过这个限制:

publicclassPrivateCarReflect{
publicstaticvoidmain(String[]args)throwsThrowable{
ClassLoaderloader=Thread.currentThread().getContextClassLoader();
Classclazz=loader.loadClass("com.baobaotao.reflect.PrivateCar");
PrivateCarpcar=(PrivateCar)clazz.newInstance();
FieldcolorFld=clazz.getDeclaredField("color");
//①取消Java语言访问检查以访问private变量
colorFld.setAccessible(true);
colorFld.set(pcar,"红色");

MethoddriveMtd=clazz.getDeclaredMethod("drive",(Class[])null);
//MethoddriveMtd=clazz.getDeclaredMethod("drive");JDK5.0下使用

//②取消Java语言访问检查以访问protected方法
driveMtd.setAccessible(true);
driveMtd.invoke(pcar,(Object[])null);
}
}

//运行该类,打印出以下信息:
//引用
drive private car! the color is:红色

在访问private、protected成员变量和方法时必须通过setAccessible(boolean access)方法取消Java语言检查,否则将抛出IllegalAccessException。如果JVM的安全管理器设置了相应的安全机制,调用该方法将抛出SecurityException。

beanfactory和applicationcontext

Spring 通过一个配置文件来描述 Bean 及 Bean 之间的依赖关系,利用 Java 的反射功能实例化 Bean 并建立 Bean 之间的依赖关系 。Sprig 的 IoC 容器在完成这些底层工作的基础上,还提供了 Bean 实例缓存 、 生命周期管理 、Bean 实例代理 、 事件发布 、 资源装载等高级服务 。

Bean 工厂( com.springframework.beans.factory.BeanFactory )是 Spring 框架中最核心的接口,它提供了高级 IoC 的配置机制 。BeanFactory 使管理不同类型的 Java 对象成为可能。而应用上下文( com.springframework.context.ApplicationContext )建立在 BeanFactory 基础之上,提供了更多面向应用的功能,它提供了资源、国际化支持和框架事件体系,更易于创建实际应用 。我们一般称 BeanFactory 为 IoC 容器,而称 ApplicationContext 为应用上下文或 Spring 容器 。

BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身; ApplicationContext 面向使用 Spring 框架的开发者,几乎所有的应用场合都可以直接使用 ApplicationContext。

BeanFactory和FactoryBean

一般情况下,Spring通过反射机制利用bean的class属性制定实现类实例化bean。在默写情况下,实例化bean的过程比较复杂,需要提供大量的配置信息,配置方式的灵活性受限,这是采用编码的方式是一个简单的方案,用户可以通过实现该工厂类解耦实例化bean的逻辑,这是factoryBean作用就体现出来。

FactoryBean接口对于Spring框架来说占重要地位,Spring自身提供了很多FactoryBean的实现类。

BeanFactory是接口,提供了IOC容器最基本的形式,给具体的IOC容器的实现提供了规范,

FactoryBean也是接口,为IOC容器中Bean的实现提供了更加灵活的方式,FactoryBean在IOC容器的基础上给Bean的实现加上了一个简单工厂模式和装饰模式(如果想了解装饰模式参考:修饰者模式(装饰者模式,Decoration)我们可以在getObject()方法中灵活配置。其实在Spring源码中有很多FactoryBean的实现类.

FactoryBean支持的三个接口方法:
T getObject():返回由FactoryBean创建的Bean实例,如果isSingleton()返回true,则该实例会放到Spring容器中单实例缓存池中;
Boolean isSingleton():返回由FactoryBean创建的Bean实例的作用域是singleton还是prototype;
Class getObjectType():返回FactoryBean创建的Bean类型。

类装载器ClassLoader

摘要:类装载器就是寻找类的字节码并构造出类在JVM内部表示对象的组件。在Java中,类装载器把一个类装入JVM中,需要经过以下几个步骤:1.装载:查找和导入Class文件,即Java字节码文件;2.链接:执行校验、准备和解析步骤,其中解析步骤是可以选择的:a)校验:检查载入的Class文件数据的正确性;b)装备:给类的静态变量分配存储空间(注意:这里仅仅为静态变量非配存储空间,而并未进行初始化操作,也就是说这时候静态变量还未被初始化)c)解析:将符号引用转成直接引用;3.链接:对类
类装载器就是寻找类的字节码并构造出类在JVM内部表示对象的组件。在Java中,类装载器把一个类装入JVM中,需要经过以下几个步骤:

  1. 装载:查找和导入Class文件,即Java字节码文件;
  2. 链接:执行校验、准备和解析步骤,其中解析步骤是可以选择的: a) 校验:检查载入的Class文件数据的正确性;
    b) 装备:给类的静态变量分配存储空间(注意:这里仅仅为静态变量非配存储空间,而并未进行初始化操作,也就是说这时候静态变量还未被初始化)
    c) 解析:将符号引用转成直接引用;
  3. 链接:对类的静态变量、静态代码块执行初始化工作。

类装载工作由ClassLoader及其子类负责,它们负责在运行时查找和装入Class字节码文件。JVM在运行时会产生三个ClassLoader:根装载器、ExtClassLoader(扩展类装载器)和AppClassLoader(系统类装载器)。其中,根装载器不是ClassLoader的子类,它使用C++编写,而ExtClassLoader和AppClassLoader都是ClassLoader的子类。其中根装载器负责装载JRE的核心类库,如JRE目标下的rt.jar、charsets.jar等;ExtClassLoader负责装载JRE扩展目录ext中的JAR类包;AppClassLoader负责装载Classpath路径下的类包(即应用程序的类)。

这三个类装载器之间实际上存在父子层级关系,即根装载器是ExtClassLoader的父装载器,ExtClassLoader是AppClassLoader的父装载器。默认情况下,使用AppClassLoader装载应用程勋的类。

下面简单介绍一下JVM装载类的机制。JVM装载类时使用“全盘负责委托机制”,“全盘负责”是指当一个ClassLoader装载一个类时,除非显示地使用另一个ClassLoader,该类(被装载的类)所依赖及引用的类也由这个ClassLoader载入;“委托机制”是指委托父装载器寻找目标类,只有在找不到的情况下才从自己的类路径中查找并装载目标类(也就是在加载每个Class时,都会先由父装载器尝试寻找目标类,只有在找不到的情况下才从自己的类路径中查找并装载目标类,此时则使用AppClassLoader。顺序依次是:根装载器–ExtClassLoader–AppClassLoader)。这一点是从安全角度考虑的,试想如果有人编写了一个恶意的基础类(如java.lang.String)并装载到JVM中将会引发多么可怕的结果。但是由于有了“全盘负责委托机制”,java.lang.String永远是由根装载器来装载的,这样就避免了上述事件的发生。

Spring aop 原理

说起AOP就不得不说下OOP了,OOP中引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。但是,如果我们需要为部分对象引入公共部分的时候,OOP就会引入大量重复的代码。例如:日志功能。
  AOP技术利用一种称为“横切”的技术,解剖封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,这样就能减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理。

方面(Aspect):一个关注点的模块化,这个关注点实现可能另外横切多个对象。事务管理是J2EE应用中一个很好的横切关注点例子。方面用spring的 Advisor或拦截器实现。

AOP重要术语

  • 连接点(Joinpoint): 程序执行过程中某个特定的位置,如方法的调用或特定的异常被抛出。
  • 通知(Advice): 在特定的连接点,AOP框架执行的动作。各种类型的通知包括“around”、“before”和“throws”通知。通知类型将在下面讨论。许多AOP框架包括Spring都是以拦截器做通知模型,维护一个“围绕”连接点的拦截器链。Spring中定义了四个advice: BeforeAdvice, AfterAdvice, ThrowAdvice和DynamicIntroductionAdvice
  • 切入点(Pointcut): 指定一个通知将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切入点:例如,使用正则表达式。 Spring定义了Pointcut接口,用来组合MethodMatcher和ClassFilter,可以通过名字很清楚的理解, MethodMatcher是用来检查目标类的方法是否可以被应用此通知,而ClassFilter是用来检查Pointcut是否应该应用到目标类上
  • 引入(Introduction): 添加方法或字段到被通知的类。 Spring允许引入新的接口到任何被通知的对象。例如,你可以使用一个引入使任何对象实现 IsModified接口,来简化缓存。Spring中要使用Introduction, 可有通过DelegatingIntroductionInterceptor来实现通知,通过DefaultIntroductionAdvisor来配置Advice和代理类要实现的接口
  • 目标对象(Target Object): 包含连接点的对象。也被称作被通知或被代理对象。POJO
  • AOP代理(AOP Proxy): AOP框架创建的对象,包含通知。 在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。
  • 织入(Weaving): 组装方面来创建一个被通知对象。这可以在编译时完成(例如使用AspectJ编译器),也可以在运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。
  • 切面(Aspect):切面有切点、通知、引介组成,它既包括横切逻辑定义,也包括连接点定义

Aop代理

静态代理
动态代理:
JDK 动态代理
cgLib动态代理
Spring aop 使用两种代理机制:一种基于JDK 的动态代理;另一种是基于CGLib动态代理。原因:JDK本身值提供接口的代理,而不支持类的代理,当接口(JDK代理),当类(CGLIB)
JDK动态代理:
代理模式的UML图

在这里插入图片描述

从UML图中,可以看出代理类与真正实现的类都是继承了抽象的主题类,这样的好处在于代理类可以与实际的类有相同的方法,可以保证客户端使用的透明性。
代理模式的实现

代理模式可以有两种实现的方式,一种是静态代理类,另一种是各大框架都喜欢的动态代理。下面我们主要讲解一下这两种代理模式

静态代理

我们先看针对上面UML实现的例子,再看静态代理的特点。

//Subject接口的实现

public interface Subject {
    void visit();
}
//实现了Subject接口的两个类:
public class RealSubject implements Subject {
    private String name = "byhieg";
    @Override
    public void visit() {
        System.out.println(name);
    }
}
public class ProxySubject implements Subject{
    private Subject subject;
    public ProxySubject(Subject subject) {
        this.subject = subject;
    }
    @Override
    public void visit() {
        subject.visit();
    }
}
//具体的调用如下:
public class Client {
    public static void main(String[] args) {
        ProxySubject subject = new ProxySubject(new RealSubject());
        subject.visit();
    }
}

通过上面的代理代码,我们可以看出代理模式的特点,代理类接受一个Subject接口的对象,任何实现该接口的对象,都可以通过代理类进行代理,增加了通用性。但是也有缺点,每一个代理类都必须实现一遍委托类(也就是realsubject)的接口,如果接口增加方法,则代理类也必须跟着修改。其次,代理类每一个接口对象对应一个委托对象,如果委托对象非常多,则静态代理类就非常臃肿,难以胜任。

动态代理

动态代理有别于静态代理,是根据代理的对象,动态创建代理类。这样,就可以避免静态代理中代理类接口过多的问题。动态代理是实现方式,是通过反射来实现的,借助Java自带的java.lang.reflect.Proxy,通过固定的规则生成。
其步骤如下:

编写一个委托类的接口,即静态代理的(Subject接口)
实现一个真正的委托类,即静态代理的(RealSubject类)
创建一个动态代理类,实现InvocationHandler接口,并重写该invoke方法
在测试类中,生成动态代理的对象。

第一二步骤,和静态代理一样,不过说了。第三步,代码如下:

public class DynamicProxy implements InvocationHandler {
    private Object object;
    public DynamicProxy(Object object) {
        this.object = object;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = method.invoke(object, args);
        return result;
    }
}

第四步,创建动态代理的对象

Subject realSubject = new RealSubject();
DynamicProxy proxy = new DynamicProxy(realSubject);
ClassLoader classLoader = realSubject.getClass().getClassLoader();
Subject subject = (Subject) Proxy.newProxyInstance(classLoader, new  Class[]{Subject.class}, proxy);
subject.visit();

创建动态代理的对象,需要借助Proxy.newProxyInstance。该方法的三个参数分别是:
ClassLoader loader表示当前使用到的appClassloader。
Class<?>[] interfaces表示目标对象实现的一组接口。
InvocationHandler h表示当前的InvocationHandler实现实例对象。
Cglib代理: 针对类来实现代理,对指定目标
产生一个子类 通过方法拦截技术拦截所有父类方法的调用。

我们要使用cglib代理必须引入 cglib的jar包

//轮船类
package com.zs.spring.demo1;
public class Ship {
    public void travel(){
        System.out.println("轮船正在行驶");
    }
//代理类 输出日志
package com.zs.spring.demo1;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class ShipProxy implements MethodInterceptor {
//通过Enhancer 创建代理对象
    private Enhancer enhancer = new Enhancer();
    //通过Class对象获取代理对象
    public Object getProxy(Class c){
        //设置创建子类的类
        enhancer.setSuperclass(c);
        enhancer.setCallback(this);
        return enhancer.create();
    }
    @Override
    public Object intercept(Object obj, Method m, Object[] args, MethodProxy proxy) throws Throwable {
        // TODO Auto-generated method stub
        System.out.println("日志开始...");
        //代理类调用父类的方法
        proxy.invokeSuper(obj, args);
        System.out.println("日志结束...");
        return null;
    }
}
//创建我的测试类
package com.zs.spring.demo1;
public class TestCgibl {
    public static void main(String[] args) {
        //创建我们的代理类
        ShipProxy Proxy = new ShipProxy();
        Ship ship = (Ship)Proxy.getProxy(Ship.class);
        ship.travel();

    }

}

输出:
日志开始…
轮船正在行驶
日志结束…

外传

😜 原创不易,如若本文能够帮助到您的同学
🎉 支持我:关注我+点赞👍+收藏⭐️
📝 留言:探讨问题,看到立马回复
💬 格言:己所不欲勿施于人 扬帆起航、游历人生、永不言弃!🔥

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/549035.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

学术会议参会经验分享一(参会前的准备工作)

前前后后参加了两次学术会议&#xff0c;一次是今年三月份在深圳&#xff0c;另一次是在五月份在南宁&#xff0c;并且两次都进行了主题演讲。总的来说&#xff0c;我感觉参加学术会议重要的是自身能力的提升&#xff0c;比如说演讲、PPT制作等更方面的能力。下面我来分享一些我…

USRP概念基础

GBIC Gigabit Interface Converter的缩写,是将千兆位电信号转换为光信号的接口器件。GBIC设计上可以为热插拔使用。 SFP SFP (Small Form Pluggable)可以简单理解为GBIC(Gigabit Interface Converter的缩写)升级版本,是将千兆位电信号转换为光信号的接口器件,可以热插…

python字符串拼接

首先 什么是字符串拼接 我们来看一个段代码 print("你好""小猫猫")运行结果如下 这是一个最简单的演示 字符串 与 字符串的拼接 两个字符串字面量可以直接用加号 合并成一个字符串 当然 直接这里 字面量字面量 直接写上去看着会非常傻 所以 一般都是 变…

( 动态规划) 516. 最长回文子序列 ——【Leetcode每日一题】

❓516. 最长回文子序列 难度&#xff1a;中等 给你一个字符串 s &#xff0c;找出其中最长的回文子序列&#xff0c;并返回该序列的长度。 子序列定义为&#xff1a;不改变剩余字符顺序的情况下&#xff0c;删除某些字符或者不删除任何字符形成的一个序列。 示例 1&#xf…

MarkDown语法2

MarkDown语法2 一、基本语法 1. 标题 一级标题&#xff1a;# 一级标题二级标题&#xff1a;## 二级标题 2. 字体 斜体&#xff1a;*斜体*,_斜体_粗体&#xff1a;**粗体**&#xff0c;__粗体__粗斜体&#xff1a;***粗斜体***, ___粗斜体___ 3. 线 分割线&#xff1a;&a…

java常用工具之Objects类

目录 简介一、对象判空二、 对象为空时抛异常三、 判断两个对象是否相等四、 获取对象的hashcode五、 比较两个对象六、比较两个数组七、 小结 简介 Java 的 Objects 类是一个实用工具类&#xff0c;包含了一系列静态方法&#xff0c;用于处理对象。它位于 java.util 包中&…

七、Spring Cloud Alibaba-Sentinel

一、引言 1、了解服务可用性问题&#xff0c;服务挂掉原因 缓存击穿、单点故障、流量激增、线程池爆满、CPU飙升、DB超时、缺乏容错机制或保护机制、负载不均、服务雪崩、异常没处理等。 服务雪崩效应&#xff1a;因服务提供者的不可用导致服务调用者的不可用&#xff0c;并将…

Doxygen源码分析: QCString类依赖的qstr系列C函数浅析

2023-05-20 17:02:21 ChrisZZ imzhuofoxmailcom Hompage https://github.com/zchrissirhcz 文章目录 1. doxygen 版本2. QCString 类简介3. qstr 系列函数浅析qmemmove()qsnprintfqstrdup()qstrfree()qstrlen()qstrcpy()qstrncpy()qisempty()qstrcmp()qstrncmp()qisspace()qstr…

C++ VTK网格模型补洞填孔

程序示例精选 C VTK网格模型补洞填孔 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对<<C VTK网格模型补洞填孔>>编写代码&#xff0c;代码整洁&#xff0c;规则&#xff0c;易读。…

如何将Windows图片查看器的背景颜色改成浅色?

现在大家基本都在使用Win10系统&#xff0c;我们在双击查看图片时&#xff0c;系统默认使用系统自带的图片&#xff08;照片&#xff09;查看器去打开图片。图片查看器的背景色默认是黑色的&#xff0c;如下所示&#xff1a;&#xff08;因为大家可能会遇到同样的问题&#xff…

飞浆AI studio人工智能课程学习(3)-在具体场景下优化Prompt

文章目录 在具体场景下优化Prompt营销场景办公效率场景日常生活场景海报背景图生成办公效率场景预设Prompt 生活场景中日常学习Prompt: 给写完的代码做文档 将优质Prompt模板化Prompt 1:Prompt 1:Prompt 2步骤文本过长而导致遗失信息的示例修改后 特殊示例 如何提升安全性主要目…

最近最少使用(LRU, Least recently used)缓存算法_华为2023

思路 性能限制很高、数据量很大时&#xff0c;cin、cout肯定是不够快的。 &#xff08;1&#xff09;可以利用getchar()速度快的特性设计快读函数读取整数&#xff0c;可以做到用scanf()函数5倍的速度读入任意整数&#xff1a; #include<cstdio> // 仅正整数可用 #defi…

u盘恢复数据方法有哪些(u盘恢复数据方法)

嘿小伙伴们&#xff0c;今天咱们来聊聊一个小问题&#xff0c;就是当我们的U盘不小心丢失了重要数据&#xff0c;怎么办呢&#xff1f;没关系&#xff0c;这里我就为大家介绍几种U盘恢复数据的方法。 u盘恢复数据方法有哪些 1,首先&#xff0c;最简单粗暴的方法就是使用Windo…

Redis分片集群

目录 搭建分片集群 散列插槽 集群伸缩 故障转移 数据迁移 RedisTemplate访问分片集群 搭建分片集群 主从&#xff08;一个主节点、多个子节点&#xff0c;读写分离&#xff09;和哨兵&#xff08;解决主节点宕机问题&#xff09;可以解决高可用、高并发读的问题。但是依然…

如何更改pdf文件的默认打开程序?

在Windows系统中&#xff0c;有时安装一些软件或执行一些操作&#xff0c;会自动将打开某种类型文件的默认程序给修改掉&#xff0c;这样后续打开文件时可能会很别扭&#xff0c;于是我们想把打开文件的默认工具设置指定的软件。 以打开pdf文件为例&#xff0c;某天打开pdf文件…

基于Zynq的雷达10Gbps高速PCIE数据采集卡方案(三)软件设计

4.1 引言 本章基于第二章的分析结论&#xff0c;进行系统软件设计。软件设计包括逻辑设计、嵌入 式软件设计和上位机软件设计。在逻辑设计中&#xff0c;对 ADC 模块、 Aurora 模块、 DDR3 SDRAM 模块和 PCIE 模块进行分析和设计&#xff0c;在 Vivado 软件提供的 …

BI技巧丨计算组柱形图

PowerBI中&#xff0c;我们经常使用柱形图来进行趋势对比分析&#xff0c;通过柱形图我们可以直观展示每个月之间的差异。 但是在实际需求中&#xff0c;PowerBI原生的柱形图仅能展示一个数据标签&#xff0c;如果我们想要展示同环比的变化情况&#xff0c;往往需要将同环比的…

Metal入门学习:GPU并行计算大数组相加

一、编程指南PDF下载链接(中英文档&#xff09; 1、Metal编程指南PDF链接 https://github.com/dennie-lee/ios_tech_record/raw/main/Metal学习PDF/Metal 编程指南.pdf 2、Metal着色语言(Metal Shader Language:简称MSL)编程指南PDF链接 https://github.com/dennie-lee/ios_te…

【王道·计算机网络】第六章 应用层

一、基本概念 1.1 应用层概述 应用层对应用程序的通信提供服务应用层协议定义&#xff1a; 应用进程交换的报文类型&#xff0c;请求还是响应?各种报文类型的语法&#xff0c;如报文中的各个字段及其详细描述字段的语义&#xff0c;即包含在字段中的信息的含义进程何时、如何…

PathWise开发(1) 将增加节点的功能移动到鼠标右键 d3.js/vue.js

PathWise(1) 从零开始搭建知识图谱/个性化学习路径/d3.js/vue.js 2023年5月20日&#xff1a;将增加节点的功能移动到鼠标右键 跑起来先 思路&#xff1a; 将我们之前的MyTableAddNode.vue&#xff0c;删除其中的内容只留下下面的表单<template><!-- <div class…