Spring方法注入

Wesley13
• 阅读 578

在spring中注入方式有3中:

1, 构造函数注入

2, set方法注入

3, 接口注入(方法注入)

在spring中的bean默认范围都是单例, 但是在特定的情况下, 我们需要有如下的业务需要, 单例bean1需要依赖非单例bean2, 由于bean1始终是单例,所以如果不做出改变,每次获取的bean2也是同一个, 容器就没办法给我们提供一个新的bean2.

spring提供了如下方法:

1, 非ioc, 通过bean1实现ApplicationContextAware接口, 利用ApplicatioinContext在需要的时候getBean("bean1");

2, lookup方式

3, 其他

常用的1、2种方式

利用非IOC方式:

package org.xyz.svc.impl;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.xyz.svc.UserSvc;
import org.xyz.vo.User;

public class UserSvcImpl implements UserSvc, ApplicationContextAware{
    
    private ApplicationContext context;

    @Override
    public User initUser() {
        return (User)context.getBean("User");
    }

    @Override
    public void setApplicationContext(ApplicationContext context)
            throws BeansException {
        this.context = context;
    }

}

applicationContext.xml :

<?xml version="1.0" encoding="UTF-8"?>
<!--
  - Middle tier application context definition for the image database.
  -->
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
                http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
    <bean name = "User" class = "org.xyz.vo.User" scope="prototype"></bean>

    <bean name="UserSvc" class = "org.xyz.svc.impl.UserSvcImpl">
    </bean>
    
</beans>

TestCase:

package test;

import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.xyz.svc.UserSvc;

public class TestUserSvc {
    
    private ApplicationContext applicationContext;
    
    @Before
    public void init() throws Exception{
        applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    }
    
    @Test
    public void testProcess(){
        UserSvc userSvc = (UserSvc)applicationContext.getBean("UserSvc", UserSvc.class);
        
        System.out.println(userSvc.initUser());
        System.out.println(userSvc.initUser());
        System.out.println(userSvc.initUser());
    }

}

运行结果:

org.xyz.vo.User@10f6d3
org.xyz.vo.User@1bcc0bc
org.xyz.vo.User@111a3a4

这种方式还是与spring framework产生了耦合,可以看到获取User的时候,指定了bean2的名称.

推荐使用下面的lookup方式实现, 因为这种方式使用了代理,spring利用cglib生成了需要的子类.

 去掉实现接口ApplicationContextAware, 定义抽象获取user的的方法为抽象方法

package org.xyz.svc.impl;

import org.xyz.svc.UserSvc;
import org.xyz.vo.User;

public abstract class UserSvcImpl implements UserSvc{
    
    public User initUser() {
        return createUser();
    }
    
    public abstract User createUser();

}

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--
  - Middle tier application context definition for the image database.
  -->
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
                http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
    <bean name = "User" class = "org.xyz.vo.User" scope="prototype"></bean>

    <bean name="UserSvc" class = "org.xyz.svc.impl.UserSvcImpl">
        <lookup-method name="createUser" bean="User"/>
    </bean>
    
</beans>

TestCase

运行结果:

org.xyz.vo.User@6f50a8
org.xyz.vo.User@187814
org.xyz.vo.User@73a7ab

实现了我们想要的需求了.

注意:  被注入的方法定义要求: 

<public|protected> [abstract] <return-type> theMethodName(no-arguments);

如果是抽象方法,会被spring动态生产的子类实现,如果不是抽象,会被覆盖. 所以类和方法修饰符不可以为final.

点赞
收藏
评论区
推荐文章
从源码层面深度剖析Spring循环依赖
作者:郭艳红以下举例皆针对单例模式讨论图解参考1、Spring如何创建Bean?对于单例Bean来说,在Spring容器整个生命周期内,有且只有一个对象。Spring在创建Bean过程中,使用到了三级缓存,即DefaultSingletonBeanRegi
Easter79 Easter79
3年前
SpringIOC官方文档解读
IoC容器本章介绍了Spring的控制反转(IoC)容器。1.1。SpringIoC容器和Bean简介本章介绍了反转控制(IoC)原则的Spring框架实现。IoC也称为依赖注入(DI)。在此过程中,对象可以通过①构造函数参数(),②工厂方法的参数③或在构造或从工厂方法返回后在对象实例上设置的属性来定义其依
Easter79 Easter79
3年前
Spring一些问题记录
1、在非springbean中注入bean        在项目中有时需要根据需要在自己new一个对象,或者在某些util方法或属性中获取SpringBean对象,从而完成某些工作,但是由于自己new的对象和util方法并不是受Spring所管理的,如果直接在所依赖的属性上使用@Autowired就会报无法注入的错误,或者是没报错,但是使用的时候会
Stella981 Stella981
3年前
Spring 必知概念(二)
13、Spring框架中的单例Beans是线程安全的么?Spring框架并没有对单例bean进行任何多线程的封装处理。关于单例bean的线程安全和并发问题需要开发者自行去搞定。但实际上,大部分的Springbean并没有可变的状态(比如Serview类和DAO类),所以在某种程度上说Spring的单例bean是线程安全的。如果你的bean有多
Easter79 Easter79
3年前
Spring容器中Bean的作用域
当通过Spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为Bean指定特定的作用域。Spring支持如下5种作用域:singleton:单例模式,在整个SpringIoC容器中,使用singleton定义的Bean将只有一个实例prototype:原型模式,每次通过容器
Stella981 Stella981
3年前
Spring3.1.0实现原理分析(八).获取bean对象
   Spring获取bean对象的逻辑相对简单,原本不打算专门写篇博客来介绍了。不过想了想,既然上两篇博客分析了Spring创建对象的过程,有创建便有获取,所以还是分析下获取bean对象的过程吧。一.获取单例bean1).进入DefaultSingletonBeanRegistry的getSingleton方法,下面是代码片段,简单
Easter79 Easter79
3年前
Spring常用的三种注入方式
Spring通过DI(依赖注入)实现IOC(控制反转),常用的注入方式主要有三种:构造方法注入,setter注入,基于注解的注入。构造方法注入先简单看一下测试项目的结构,用maven构建的,四个包:entity:存储实体,里面只有一个User类dao:数据访问,一个接口,两个实现类service:服务层,一个接口,一个
Easter79 Easter79
3年前
Spring两种依赖注入方式的比较
我们知道,Spring对象属性的注入方式有两种:设值注入和构造注入。先看代码:  假设有个类为People,该对象包含三个属性,name和school还有age,这些属性都有各自的setter和getter方法,还有一个包含这三个属性的构造方法。如果用spring来管理这个对象,那么有以下两种方式为People设置属性:  1.设值注入:
Wesley13 Wesley13
3年前
C#中依赖注入
由于客户类只依赖于服务类的一个接口,而不依赖于具体服务类,所以客户只定义一个注入点。在程序运行过程中,客户类部直接实例化具体服务类实例,而是客户类的运行上下文环境或者专门组建负责实例化服务类,然后将其注入到客户类中,保证客户类的正常运行。依赖注入的方法大致分为3中:接口注入、构造方法注入、setter注入;1、setter注入setter注入是指
当我们在谈论构造函数注入的时候我们在谈论什么 | 京东物流技术团队
依赖注入当涉及依赖注入(DependencyInjection,DI)时,首先推荐使用构造函数注入,因为构造函数注入有很多技术优点,而且还与面向对象的设计原则密切相关。在业界,构造函数注入作为依赖注入的一种最佳实践得到了广泛的认可,在SpringFrame