Spring面试题系列-4

简介: Spring面试题系列-4


Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。

什么是AOP,AOP的作用和优势

AOP(Aspect-Oriented Programming,面向切面编程)是一种编程范式,它允许开发者将横切关注点(cross-cutting concerns)从应用程序的主要业务逻辑中分离出来,以便更好地实现代码重用和模块化

AOP的作用主要体现在以下几个方面:

  1. 减少重复代码:通过将横切关注点如日志记录、事务管理等通用功能集中处理,可以避免在多个模块中重复编写相同或类似的代码。
  2. 提高开发效率:由于横切关注点被模块化,开发者可以专注于业务逻辑的开发,从而提高开发效率。
  3. 维护方便:当需要修改横切关注点时,只需在一个地方进行修改,而不需要查找分散在各个模块中的相关代码,这大大简化了维护工作。
  4. 动态性强:AOP提供了在运行时动态改变程序行为的能力,这意味着可以在不修改源代码的情况下增加或改变功能。
  5. 可重用性:横切关注点的模块化使得这些功能可以被不同的模块重用,提高了代码的可重用性。
  6. 降低耦合度:通过将横切关注点与业务逻辑分离,降低了系统各部分之间的耦合度,有助于构建更加清晰和易于理解的系统架构。

总的来说,AOP的优势在于它提供了一种机制,使得那些散布在应用程序多个模块中的横切关注点能够被统一管理和封装,从而提升了软件的可维护性和可扩展性。

什么是动态代理

动态代理是一种在程序运行时动态生成的代理对象,它能够增强或控制对其他对象的访问

动态代理是设计模式中代理模式的一种实现方式,与静态代理相比,它不需要在编译期就确定代理类和被代理类的关系。动态代理的主要优点在于其灵活性和扩展性,它可以在运行时根据需要为任意类生成代理对象,实现方法的委托。这种机制常用于以下场景:

  • 日志记录:通过代理对象在调用目标方法前后添加日志记录逻辑。
  • 权限检查:在调用目标方法前进行权限验证,以确保安全性。
  • 事务管理:在方法调用前后管理数据库事务,确保数据的一致性。

在Java中,动态代理主要有两种实现方式:

  • 基于接口的动态代理:使用JDK提供的java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口来实现。这种方式要求目标类实现一个或多个接口。
  • 基于类的动态代理:使用第三方库如CGLib(Code Generation Library)来实现。CGLib可以在不实现任何接口的情况下创建目标类的代理,它通过继承目标类并覆盖其方法来实现代理功能。

总的来说,动态代理是一种强大的技术,它使得开发者能够在不修改原有代码的基础上,为对象的方法添加额外的行为,从而实现代码的解耦和功能的扩展。

动态代理常用的两种方式

动态代理常用的两种方式是基于接口的动态代理和基于类的动态代理

首先,基于接口的动态代理是通过Java的反射机制实现的。这种方式要求被代理的对象实现一个或多个接口,然后通过java.lang.reflect.Proxy类的newProxyInstance方法来创建代理对象。这个代理对象实现了与被代理对象相同的接口,并且在调用方法时会通过InvocationHandler接口的实现类来处理,这样就能够在不改变原有代码的基础上增强或者控制对真实对象的访问。

其次,基于类的动态代理通常使用第三方库如CGLib(Code Generation Library)来实现。它不要求被代理对象实现接口,而是通过继承被代理类并覆盖其方法来创建代理。这种方式适用于没有实现任何接口的类,它提供了更多的灵活性,但也可能需要额外的依赖,如ASM库。

总的来说,这两种方式各有优势,基于接口的动态代理更加轻量级且不需要额外依赖,而基于类的动态代理则提供了更广泛的应用范围。在实际应用中,选择哪种方式取决于具体的需求和场景。

jdk动态代理如何实现

JDK动态代理实现的步骤如下:

  1. 定义一个接口,例如Subject
  2. 创建一个实现了该接口的类,例如RealSubject
  3. 创建一个实现了InvocationHandler接口的类,例如MyInvocationHandler
  4. MyInvocationHandler中重写invoke方法,实现代理逻辑。
  5. 使用Proxy.newProxyInstance()方法创建代理对象。

以下是一个简单的示例:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 定义一个接口
interface Subject {
    void doSomething();
}
// 创建一个实现了该接口的类
class RealSubject implements Subject {
    @Override
    public void doSomething() {
        System.out.println("RealSubject do something");
    }
}
// 创建一个实现了InvocationHandler接口的类
class MyInvocationHandler implements InvocationHandler {
    private Object target;
    public MyInvocationHandler(Object target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before method call");
        Object result = method.invoke(target, args);
        System.out.println("After method call");
        return result;
    }
}
public class Main {
    public static void main(String[] args) {
        // 创建被代理对象
        Subject realSubject = new RealSubject();
        // 创建代理处理器
        MyInvocationHandler handler = new MyInvocationHandler(realSubject);
        // 创建代理对象
        Subject proxySubject = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), handler);
        // 调用代理对象的方法
        proxySubject.doSomething();
    }
}

运行上述代码,输出结果如下:

Before method call
RealSubject do something
After method call

Cglib的Enhaner实现动态代理?

Cglib是一个第三方的代码生成库,它通过扩展被代理类来实现动态代理。Cglib的Enhancer是实现动态代理的核心类,它可以为目标对象生成一个子类,并在子类中添加代理逻辑。

以下是使用Cglib的Enhancer实现动态代理的步骤:

  1. 引入Cglib依赖

在项目的pom.xml文件中添加Cglib的依赖:

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>
  1. 创建目标对象接口

创建一个目标对象的接口,例如:

public interface Target {
    void doSomething();
}
  1. 创建目标对象实现类

创建一个目标对象的实现类,例如:

public class TargetImpl implements Target {
    @Override
    public void doSomething() {
        System.out.println("Target is doing something");
    }
}
  1. 创建代理逻辑类

创建一个代理逻辑类,例如:

public class ProxyLogic {
    public void before() {
        System.out.println("Before method call");
    }
    public void after() {
        System.out.println("After method call");
    }
}
  1. 使用Enhancer创建代理对象

使用Cglib的Enhancer创建代理对象,并为目标对象添加代理逻辑:

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibProxyDemo {
    public static void main(String[] args) {
        // 创建目标对象实例
        Target target = new TargetImpl();
        // 创建Enhancer实例
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(new MethodInterceptor() {
            private ProxyLogic proxyLogic = new ProxyLogic();
            @Override
            public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
                proxyLogic.before();
                Object result = proxy.invokeSuper(obj, args);
                proxyLogic.after();
                return result;
            }
        });
        // 创建代理对象
        Target proxy = (Target) enhancer.create();
        // 调用代理对象的方法
        proxy.doSomething();
    }
}

运行上述代码,输出结果如下:

Before method call
Target is doing something
After method call


相关文章
|
4月前
|
Java 应用服务中间件 开发者
Java面试题:解释Spring Boot的优势及其自动配置原理
Java面试题:解释Spring Boot的优势及其自动配置原理
117 0
|
25天前
|
设计模式 缓存 Java
面试题:谈谈Spring用到了哪些设计模式?
面试题:谈谈Spring用到了哪些设计模式?
|
5月前
|
消息中间件 缓存 Java
Spring Boot最经典的20道面试题,你都会了吗?
Spring Boot最经典的20道面试题,你都会了吗?
165 0
|
30天前
|
Java 程序员 Spring
Spring事务的1道面试题
每次聊起Spring事务,好像很熟悉,又好像很陌生。本篇通过一道面试题和一些实践,来拆解几个Spring事务的常见坑点。
Spring事务的1道面试题
|
1月前
|
XML 前端开发 Java
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
本文阐述了Spring、Spring Boot和Spring MVC的关系与区别,指出Spring是一个轻量级、一站式、模块化的应用程序开发框架,Spring MVC是Spring的一个子框架,专注于Web应用和网络接口开发,而Spring Boot则是对Spring的封装,用于简化Spring应用的开发。
85 0
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
|
6月前
|
Java 数据库连接 数据库
spring--为web(1),富士康java面试题整理
spring--为web(1),富士康java面试题整理
|
2月前
|
XML Java 开发者
经典面试---spring IOC容器的核心实现原理
作为一名拥有十年研发经验的工程师,对Spring框架尤其是其IOC(Inversion of Control,控制反转)容器的核心实现原理有着深入的理解。
99 3
|
3月前
|
存储 缓存 Java
面试问Spring循环依赖?今天通过代码调试让你记住
该文章讨论了Spring框架中循环依赖的概念,并通过代码示例帮助读者理解这一概念。
面试问Spring循环依赖?今天通过代码调试让你记住
|
3月前
|
前端开发 Java 开发者
Spring常见面试总结(上)
Spring框架是为Java应用提供全面支持的平台,帮助开发者处理基础任务,专注于业务逻辑。它具备IOC(控制反转)和AOP(面向切面编程)等功能,支持MVC架构、事务管理和JDBC异常处理。Spring的IOC容器负责对象的创建、配置及生命周期管理。依赖注入包括构造函数、setter和接口注入等方式。`@Component`、`@Controller`、`@Repository`和`@Service`等注解用于组件识别和装配。`@Autowired`用于精确控制依赖注入。
25 0
|
5月前
|
XML 缓存 Java
大厂面试攻略:Spring框架核心要点精讲
Java SPI (Service Provider Interface) 是一种服务发现机制,允许在运行时动态加载和发现服务提供者。在数据库驱动加载中,SPI使得数据库驱动能够自动识别和注册,而无需显式加载。 Spring 是一个广泛应用的轻量级框架,核心功能包括依赖注入(DI)和面向切面编程(AOP)。不使用Spring时,开发人员需要手动管理对象的创建和依赖关系,使用Servlet等基础组件完成Web开发,以及手动处理JDBC操作。Spring通过管理Bean的生命周期和依赖关系,简化了企业级应用的开发,降低了代码的侵入性。
73 1
大厂面试攻略:Spring框架核心要点精讲