在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.
 
  
  
  
 
