Spring--依赖注入 or 方法注入 ?

简介: 是不是跟 AOP 很像、但是其实是不一样的、MethodReplacer 你是永远没有办法调回被覆盖的方法的、它是完全覆盖的、而不是像 AOP 那样可以前置后置拦截。所以实际业务上很少地方可以用到这个 MethodReplacer 、能用到它的 AOP 都能做到、甚至比它灵活太多

网络异常,图片无法展示
|


依赖注入


我们在 Spring — 循环依赖 中谈到 Spring 的两种依赖注入方式

  • 构造器注入
  • 属性注入(setter注入也归属于此)
@Service
public class HelloService {
    /**
     * 属性注入
     */
    @Autowired
    private BeanFactory beanFactory;
    /**
     * 构造器注入
     */
    public HelloService(ApplicationContext applicationContext) {
    }
    /**
     * 属性注入
     * */
    @Autowired
    public void setEnvironment(Environment environment) {
        System.out.println("");
    }
}
复制代码


关于构造函数实例化策略的文章已经在 Spring 源码--Bean 实例化Spring 实例化--谁是我的候选人 已经谈及过


那么 @Autowired 放在属性上和放在 setter 方法上有什么不一样呢 ? 其实对于 Spring 来说都是一样的、都是一个注入元素。

AutowiredAnnotationBeanPostProcessor#postProcessProperties 该方法在 bean 实例化之后被调用

网络异常,图片无法展示
|

那么构造函数注入和属性注入的差别和适用场景是啥?

  • 构造函数注入注入的时机是先于属性注入的、并且是强依赖的
  • 对于那些非必需的依赖、推荐使用属性注入


方法注入


Lookup

方法注入的本质实际上是 Spring 继承你当前类、通过CGLib 产生子类并且重写需要注入的方法。

可能这么说有的不明所以,看个例子

@Service
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class PrintService {
    private int printCount;
    public void print(String name) {
        System.out.println("hi! " + name + " " + printCount++);
    }
}
@Service
public class HelloService {
    @Autowired
    private PrintService printService;
    public void sayHi(String name) {
        printService.print(name);
    }
}
复制代码


PrintService 是一个 prototype 类型的 bean、HelloService 是一个 singleton 、我的本意是每次调用 sayHi 方法的时候都能使用一个新创建的 PrintService 对象,但是单纯靠属性注入或者构造函数注入都是不能够实现的。


或许你可能会想到使用 ApplicationContext / BeanFactory 每次使用 PrintService 的时候去 Spring 中获取,这样子就能每次获取到一个新创建的实例。这样当然可以、但是既然逻辑都是这样、框架能不能帮我们做呢 ? 当然是可以的

@Service
public class HelloService {
    public void sayHi(String name) {
        getPrintService().print(name);
    }
    @Lookup("printService")
    protected PrintService getPrintService(){
        return null;
    }
}
复制代码


@Lookup 修饰的方法必须是可被子类覆盖的、如果没有设置 beanName 给 @Lookup 注解、那么则根据方法返回类型从 Spring 中获取该 bean

public @interface Lookup {
   String value() default "";
}
复制代码

网络异常,图片无法展示
|

这段代码其实我们在 Spring 源码--Bean 实例化Spring 实例化--谁是我的候选人 曾经遇到过、只是没有点进来详细了解。

如果你用 @Lookup 修饰的方法的类是通过配置类去实例化的话、那么这个注解则会失效。只有通过构造函数实例化的 bean 才能被 Spring 处理、使用 CGLib 产生子类。


MethodReplacer

第二种则是 MethodReplacer

<bean name="replacer" class="springroad.deomo.chap4.MethodReplace"> 
 </bean> 
 <bean name="testBean" class="springroad.deomo.chap4.LookupMethodBean">
  <replaced-method name="test" replacer="replacer"> </replaced-method> 
 </bean> 
复制代码
public class LookupMethodBean {
 public void test()
 {
  System.out.println("原始方法!");
 }
 }
public class MethodReplace implements MethodReplacer {
 public Object reimplement(Object obj, Method method, Object[] args)
   throws Throwable {
    System.out.println("方法已经被替换!");
  return null;
 }
}
复制代码


暂时没有找到 MethodReplacer 相关的注解、只能用原始的 xml 配置

原理跟 Lookup 也是一样的

网络异常,图片无法展示
|


是不是跟 AOP 很像、但是其实是不一样的、MethodReplacer 你是永远没有办法调回被覆盖的方法的、它是完全覆盖的、而不是像 AOP 那样可以前置后置拦截。所以实际业务上很少地方可以用到这个 MethodReplacer 、能用到它的 AOP 都能做到、甚至比它灵活太多


目录
相关文章
|
23天前
|
人工智能 自然语言处理 Java
Spring 集成 DeepSeek 的 3大方法(史上最全)
DeepSeek 的 API 接口和 OpenAI 是兼容的。我们可以自定义 http client,按照 OpenAI 的rest 接口格式,去访问 DeepSeek。自定义 Client 集成DeepSeek ,可以通过以下步骤实现。步骤 1:准备工作访问 DeepSeek 的开发者平台,注册并获取 API 密钥。DeepSeek 提供了与 OpenAI 兼容的 API 端点(例如),确保你已获取正确的 API 地址。
Spring 集成 DeepSeek 的 3大方法(史上最全)
|
5月前
|
Java Spring
在使用Spring的`@Value`注解注入属性值时,有一些特殊字符需要注意
【10月更文挑战第9天】在使用Spring的`@Value`注解注入属性值时,需注意一些特殊字符的正确处理方法,包括空格、引号、反斜杠、新行、制表符、逗号、大括号、$、百分号及其他特殊字符。通过适当包裹或转义,确保这些字符能被正确解析和注入。
330 3
|
3月前
|
Java Spring
【Spring】方法注解@Bean,配置类扫描路径
@Bean方法注解,如何在同一个类下面定义多个Bean对象,配置扫描路径
188 73
|
3月前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
3月前
|
Java Spring
一键注入 Spring 成员变量,顺序编程
介绍了一款针对Spring框架开发的插件,旨在解决开发中频繁滚动查找成员变量注入位置的问题。通过一键操作(如Ctrl+1),该插件可自动在类顶部添加`@Autowired`注解及其成员变量声明,同时保持光标位置不变,有效提升开发效率和代码编写流畅度。适用于IntelliJ IDEA 2023及以上版本。
一键注入 Spring 成员变量,顺序编程
|
3月前
|
Java 数据库 数据安全/隐私保护
轻松掌握Spring依赖注入:打造你的登录验证系统
本文以轻松活泼的风格,带领读者走进Spring框架中的依赖注入和登录验证的世界。通过详细的步骤和代码示例,我们从DAO层的创建到Service层的实现,再到Spring配置文件的编写,最后通过测试类验证功能,一步步构建了一个简单的登录验证系统。文章不仅提供了实用的技术指导,还以口语化和生动的语言,让学习变得不再枯燥。
67 2
|
5月前
|
存储 安全 Java
|
4月前
|
前端开发 Java Spring
Spring MVC源码分析之DispatcherServlet#getHandlerAdapter方法
`DispatcherServlet`的 `getHandlerAdapter`方法是Spring MVC处理请求的核心部分之一。它通过遍历预定义的 `HandlerAdapter`列表,找到适用于当前处理器的适配器,并调用适配器执行具体的处理逻辑。理解这个方法有助于深入了解Spring MVC的工作机制和扩展点。
70 1
|
4月前
|
前端开发 Java Spring
Spring MVC源码分析之DispatcherServlet#getHandlerAdapter方法
`DispatcherServlet`的 `getHandlerAdapter`方法是Spring MVC处理请求的核心部分之一。它通过遍历预定义的 `HandlerAdapter`列表,找到适用于当前处理器的适配器,并调用适配器执行具体的处理逻辑。理解这个方法有助于深入了解Spring MVC的工作机制和扩展点。
56 1
|
4月前
|
前端开发 Java Spring
Spring MVC源码分析之DispatcherServlet#getHandlerAdapter方法
`DispatcherServlet`的 `getHandlerAdapter`方法是Spring MVC处理请求的核心部分之一。它通过遍历预定义的 `HandlerAdapter`列表,找到适用于当前处理器的适配器,并调用适配器执行具体的处理逻辑。理解这个方法有助于深入了解Spring MVC的工作机制和扩展点。
54 0

热门文章

最新文章