【Java从0到架构师】Spring - 生命周期、代理

  • 静态代理 (Static Proxy)

  • 动态代理 (Dynamic Proxy)

    • JDK 动态代理 - Proxy.newProxyInstance
  • CGLib 动态代理 - Enhancer、MethodInterceptor

Java 从 0 到架构师目录:【Java从0到架构师】学习记录

学习 Spring 搭配这门课效果更好:《孙哥说Spring5》学习笔记

Gitee 代码:https://gitee.com/szluyu99/mj_java_frame/tree/master/02_Spring/

bean 的生命周期

=============================================================================

官方参考文档

【Spring5.x】对象的生命周期、配置文件参数化、自定义类型转换器、后置处理Bean

一个 bean 从出生到死亡,经历的生命周期方法是:

  1. 构造方法

  2. setter

  3. BeanNameAware 的 setBeanName

  4. ApplicationContextAware 的 setApplicationContext

可以获取到当前所处的 IoC 容器

  1. BeanPostProcessor 的 postProcessBeforeInitialization

  2. InitializingBean 的 afterPropertiesSet

  3. init-method

  4. BeanPostProcessor 的 postProcessAfterInitialization

  5. 业务方法

  6. DisposableBean 的 destroy

  7. destroy-method

第 10、11 个方法调用的场景:

12. bean 设置了 scope="singleton"

13. IoC 容器关闭:ctx.close()

构造方法

01 - UserServiceImpl

属性输入

02 - setAge - 20

让你知道一下bean的名字(id、name)

03 - BeanNameAware - setBeanName - userService

让你知道一下你在哪个容器里面

04 - ApplicationContextAware - setApplicationContext - org.springframework.context.support.ClassPathXmlApplicationContext@14acaea5, started on Fri Aug 21 21:14:50 CST 2020

初始化方法调用之前调用

05 - BeanPostProcessor - postProcessBeforeInitialization - userService

构造、注入完毕之后调用1(初始化,加载资源)

06 - InitializingBean - afterPropertiesSet

构造、注入完毕之后调用2(初始化,加载资源)

07 - init-method

初始化方法调用之后调用

08 - BeanPostProcessor - postProcessAfterInitialization - userService

业务方法

09 - UserServiceImpl - login - 123_456

销毁之前调用1(释放资源)

10 - DisposableBean - destroy

销毁之前调用2(释放资源)

11 - destroy-method

代理

=====================================================================

【Spring AOP】静态代理设计模式、Spring 动态代理开发详解、切入点详解(切入点表达式、切入点函数)

业务层的一些问题


业务层(Service)的主要内容:

  • 业务代码:业务运算、dao 操作等(必要

  • 附加代码:事务、日志、性能监控、异常处理等(可选)

在这里插入图片描述

现在的尴尬情况:

  • 在业务层加入附加代码会显得很臃肿、累赘

  • 但很多时候又好像不得不加


类比到生活中的一些问题可以更好的理解:

  • 房东只需要做自己必须要做的事情,其余事情交给中介(代理)去做

在这里插入图片描述

对于程序开发而言:

  • 业务层只需要处理好业务代码,其余的事情交给代理去做

在这里插入图片描述


代理的作用:在不修改目标类的目标方法代码的前提下,为目标方法增加额外功能

代理类中必须也有同样的目标方法

  • 代理类实现跟目标类同样的接口

  • 若目标类没有实现接口,代理类继承目标类

代理的实现方案:

  • 静态代理 (Static Proxy)

开发人员需要手动编写代理类(创建对应的 *.java 文件)

基本上,一个目标类就需要编写一个代理类

  • 动态代理 (Dynamic Proxy)程序运行过程中动态生成代理类的字节码

静态代理 (Static Proxy)


示例代码:静态代理

要代理 UserServiceImpl,需要实现 UserService 接口(或者继承目标类):

// 代理类实现跟目标类同样的接口

public class UserServiceProxy implements UserService {

private UserService target;

// 为基于setter的注入提供条件

public void setTarget(UserService target) {

this.target = target;

}

@Override

public boolean login(String username, String password) {

// 额外操作

System.out.println(“日志------------------1”);

// 调用目标类的方法实现

boolean result = target.login(username, password);

// 额外操作

System.out.println(“日志------------------2”);

return result;

}

}

// 代理类继承目标类, 也可实现静态代理

public class SkillServiceProxy extends SkillService {

private SkillService target;

public void setTarget(SkillService target) {

this.target = target;

}

@Override

public boolean save(Object skill) {

System.out.println(“SkillServiceProxy - 1”);

boolean result = target.save(skill);

System.out.println(“SkillServiceProxy - 2”);

return result;

}

}

<bean id=“userService”

class=“com.mj.proxy.UserServiceProxy”>

<bean id=“skillService”

class=“com.mj.proxy.SkillServiceProxy”>

动态代理 (Dynamic Proxy)


动态代理的常见实现方案有 2 种:

  1. JDK 自带:代理类需要实现和目标类一样的接口

  2. 开源项目 CGLib (Code Generation Library):代理类继承目标类

Spring 已经集成了 CGLib

示例代码:Spring - 动态代理

由我们手动实现代理,需要和前面所讲的 Spring 生命周期 BeanPostProcessor 结合起来,拦截每一个 bean 的生命周期,从而实现对每一个 bean 的代理(可以通过判断类名、方法等,来指定哪些对象需要代理)

JDK 动态代理 - Proxy.newProxyInstance

/**

  • 实现BeanPostProcessor接口会拦截每一个bean的生命周期
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值