Spring学习日记——DAY04(复杂对象创建,AOP静态代理)

1 复杂对象的创建

在 Spring 中,除了管理自己编写的 JavaBean,对于数据库连接、SqlSessionFactory 这类复杂对象,无法直接通过 new 或简单反射创建,需要用工厂方式管理,Spring 提供 FactoryBean、实例工厂、静态工厂 三种方案。

1.1 FactoryBean 接口

FactoryBean 是 Spring 提供的工厂接口,专门用于创建复杂对象,实现该接口需重写 3 个方法:

  • T getObject():创建并返回最终的复杂对象
  • Class<?> getObjectType():返回复杂对象的 Class 类型
  • boolean isSingleton():默认返回 true,标识对象是单例
使用规则
  • 直接根据 id 获取:拿到的是 getObject() 返回的对象

  • id 前加 & 获取:拿到的是 FactoryBean 实现类本身

    // 获取复杂对象
    Connection conn = (Connection) context.getBean("connection");
    // 获取工厂本身
    MyConnectionFactoryBean factory = (MyConnectionFactoryBean) context.getBean("&connection");

1.2 自定义 FactoryBean 原理

底层通过反射调用 FactoryBean 实现类的 getObject () 完成对象创建:

  1. 解析 XML 获取 FactoryBean 实现类全类名
  2. 反射创建工厂实例
  3. 调用 getObject() 得到复杂对象
  4. 根据 isSingleton() 决定是否缓存

1.3 普通工厂方式创建

1.3.1 实例工厂

先创建工厂实例,再调用工厂的非静态方法创建对象:

复制代码
<!-- 配置工厂实例 -->
<bean id="instanceFactory" class="com.xzit.factory.InstanceFactory"/>
<!-- 工厂创建对象 -->
<bean id="conn" factory-bean="instanceFactory" factory-method="getConnection"/>
1.3.2 静态工厂

直接调用工厂类的静态方法创建对象,无需创建工厂实例:

复制代码
<bean id="staticConn" class="com.xzit.factory.StaticFactory" factory-method="getConnection"/>

2 类型转换器

Spring 内置基础类型转换器,但日期、自定义类型等复杂转换需要手动配置。

2.1 自定义转换器步骤

  1. 实现 Converter<S, T> 接口,重写 convert 方法

    • S:源类型
    • T:目标类型

    public class DateConverter implements Converter<String, LocalDate> {
    private String pattern;
    @Override
    public LocalDate convert(String source) {
    DateTimeFormatter df = DateTimeFormatter.ofPattern(pattern);
    return LocalDate.parse(source, df);
    }
    // setter 注入格式
    public void setPattern(String pattern) {
    this.pattern = pattern;
    }
    }

  2. 注册转换器(id 固定为 conversionService)







  3. 使用:配置后 Spring 可自动将字符串转为指定日期类型


3 AOP 面向切面编程

3.1 AOP 简介

AOP(Aspect Oriented Programming):面向切面编程 ,核心是横向抽取重复代码,在不修改原业务代码的前提下,统一添加功能(权限、日志、事务、性能监控),实现解耦。

3.2 代理模式

AOP 底层基于动态代理实现,分为静态代理、JDK 动态代理、CGLIB 动态代理。

3.2.1 静态代理
  • 定义:代理类与目标类实现相同接口,代理类持有目标对象,在调用目标方法前后增强
  • 优点:简单直观
  • 缺点:耦合高、一个接口需一个代理类,不符合开闭原则
java 复制代码
// 共同接口
public interface Service { void save(); }
// 目标类
public class UserService implements Service {
    public void save() { System.out.println("保存用户"); }
}
// 代理类
public class ServiceProxy implements Service {
    private UserService target;
    public ServiceProxy(UserService target) { this.target = target; }
    public void save() {
        System.out.println("开启事务");
        target.save();
        System.out.println("提交事务");
    }
}
相关推荐
古法老登瞎折腾5 小时前
大数据智能运维实战(十一):运维 MCP 的工程化——权限、限流、审计与错误处理
java·大数据·运维·spring ai·mcp
学逆向的5 小时前
C 堆区内存管理
c语言·开发语言·网络安全
huoyueyi5 小时前
《融天AI-APP从0到1开发实录》
开发语言·lua
智能运维指南5 小时前
研制过程“两张皮“怎么破:研制一体化支撑平台的定位、能力边界与落地前提
java·前端·人工智能·嘉为蓝鲸
yz_aiks6 小时前
Spring AI 2.1 ChatMemory 已过时用什么替代:迁移到 Session Memory 实战(JDBC 存储与会话压缩)
java·spring boot·大模型·ai agent·spring ai
金銀銅鐵6 小时前
[Java] 用 GUI 展示 EnumMap 增删键值对时的内部变化
java·后端·ai编程
学长毕设6 小时前
基于SpringBoot的上门洗车服务系统设计与实现
java·spring boot·后端
jason成都7 小时前
RTKLIB-Java 多基线联合RTK:FIX率从0%到91.5%的三层根因修复
java·gnss·rtklib·rtklib_java
OpenAnolis小助手7 小时前
PHP 两个严重漏洞曝光,龙蜥社区 24 小时完成 3 版本修复
开发语言·操作系统·php·龙蜥社区
鱼宵7 小时前
Stream 终端操作一次讲透:collect、count、reduce 怎么选
java·stream·终端操作