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 都能做到、甚至比它灵活太多


目录
相关文章
|
9天前
|
Java Spring
在使用Spring的`@Value`注解注入属性值时,有一些特殊字符需要注意
【10月更文挑战第9天】在使用Spring的`@Value`注解注入属性值时,需注意一些特殊字符的正确处理方法,包括空格、引号、反斜杠、新行、制表符、逗号、大括号、$、百分号及其他特殊字符。通过适当包裹或转义,确保这些字符能被正确解析和注入。
|
21天前
|
Java 测试技术 程序员
为什么Spring不推荐@Autowired用于字段注入?
作为Java程序员,Spring框架在日常开发中使用频繁,其依赖注入机制带来了极大的便利。然而,尽管@Autowired注解简化了依赖注入,Spring官方却不推荐在字段上使用它。本文将探讨字段注入的现状及其存在的问题,如难以进行单元测试、违反单一职责原则及易引发NPE等,并介绍为何Spring推荐构造器注入,包括增强代码可读性和维护性、方便单元测试以及避免NPE等问题。通过示例代码展示如何将字段注入重构为构造器注入,提高代码质量。
|
2天前
|
前端开发 Java Spring
Spring MVC源码分析之DispatcherServlet#getHandlerAdapter方法
`DispatcherServlet`的 `getHandlerAdapter`方法是Spring MVC处理请求的核心部分之一。它通过遍历预定义的 `HandlerAdapter`列表,找到适用于当前处理器的适配器,并调用适配器执行具体的处理逻辑。理解这个方法有助于深入了解Spring MVC的工作机制和扩展点。
8 1
|
3天前
|
前端开发 Java Spring
Spring MVC源码分析之DispatcherServlet#getHandlerAdapter方法
`DispatcherServlet`的 `getHandlerAdapter`方法是Spring MVC处理请求的核心部分之一。它通过遍历预定义的 `HandlerAdapter`列表,找到适用于当前处理器的适配器,并调用适配器执行具体的处理逻辑。理解这个方法有助于深入了解Spring MVC的工作机制和扩展点。
11 1
|
8天前
|
存储 安全 Java
|
25天前
|
缓存 Java Spring
源码解读:Spring如何解决构造器注入的循环依赖?
本文详细探讨了Spring框架中的循环依赖问题,包括构造器注入和字段注入两种情况,并重点分析了构造器注入循环依赖的解决方案。文章通过具体示例展示了循环依赖的错误信息及常见场景,提出了三种解决方法:重构代码、使用字段依赖注入以及使用`@Lazy`注解。其中,`@Lazy`注解通过延迟初始化和动态代理机制有效解决了循环依赖问题。作者建议优先使用`@Lazy`注解,并提供了详细的源码解析和调试截图,帮助读者深入理解其实现机制。
19 1
|
2月前
|
Java 应用服务中间件 Spring
IDEA 工具 启动 spring boot 的 main 方法报错。已解决
IDEA 工具 启动 spring boot 的 main 方法报错。已解决
|
XML Java 数据格式
Spring【依赖注入】就是这么简单(二)
在Spring的第二篇中主要讲解了Spring Core模块的使用IOC容器创建对象的问题,Spring Core模块主要是解决对象的创建和对象之间的依赖关系,因此本博文主要讲解如何使用IOC容器来解决对象之间的依赖关系!
133 0
Spring【依赖注入】就是这么简单(二)
|
2月前
|
SQL 监控 druid
springboot-druid数据源的配置方式及配置后台监控-自定义和导入stater(推荐-简单方便使用)两种方式配置druid数据源
这篇文章介绍了如何在Spring Boot项目中配置和监控Druid数据源,包括自定义配置和使用Spring Boot Starter两种方法。
|
Java 测试技术 容器
Spring【依赖注入】就是这么简单
前言 在Spring的第二篇中主要讲解了Spring Core模块的使用IOC容器创建对象的问题,Spring Core模块主要是解决对象的创建和对象之间的依赖关系,因此本博文主要讲解如何使用IOC容器来解决对象之间的依赖关系! 回顾以前对象依赖 我们来看一下我们以前关于对象依赖,是怎么的历程 直接new对象 在最开始,我们是直接new对象给serice的userDao属性赋值.
1189 0