spring学习之方法注入

单例bean注入多例bean

MyPrototype、MyController

@Component
@Scope("prototype")
public class MyPrototype {
}
@Controller
public class MyController {
    @Autowired
    MyPrototype myPrototype;
    public MyPrototype getMyPrototype() {
        return myPrototype;
    }
}

MyConfig

@Configuration
@ComponentScan(value="com.learn.annotation2")
public class MyConfig {

}

测试代码

@Test
public void test(){
    ApplicationContext app =  new AnnotationConfigApplicationContext(MyConfig.class);
    MyController myController=app.getBean("myController",MyController.class);
    System.out.println(myController.getMyPrototype());
    System.out.println(myController.getMyPrototype());
}

运行结果如下:

可以看出,当单例myController中注入了多例的myPrototype,myPrototype对于myController还是一个实例,如果我们想每次获取的myPrototype是不一样的,要怎么办呢?

ApplicationContextAware

重写MyController,继承ApplicationContextAware接口设置ApplicationContext,并重写getMyPrototype方法通过applicationContext获取bean。

@Controller
public class MyController implements ApplicationContextAware {
    private ApplicationContext applicationContext;
    @Autowired
    MyPrototype myPrototype;

    public MyPrototype getMyPrototype() {
        return applicationContext.getBean("myPrototype",MyPrototype.class);
    }

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

测试代码不变
运行结果如下:

可以看出这两个地址不一样。但是这样的处理是不优雅的,业务代码和spring框架耦合度太高。

@Lookup

如果是XML配置的话,用lookup-method标签,比如:


    

MyController改写如下:

@Controller
public abstract class MyController{
    @Autowired
    MyPrototype myPrototype;

    public MyPrototype getMyPrototype() {
        return createMyPrototype();
    }

    @Lookup()
    protected abstract MyPrototype createMyPrototype() ;
}

测试代码等其他不变。
运行结果如下:

通过@Lookup注解,可以看出,两次的地址是不一样的。

方法替换

di.xml配置




    
        
            String
        
    

    

MyValueCalculator和ReplacementComputeValue

public class MyValueCalculator {
    public String computeValue(String input) {
        System.out.println(input);
        return "old method";
    }
}
public class ReplacementComputeValue implements MethodReplacer {

    @Override
    public Object reimplement(Object o, Method method, Object[] objects) throws Throwable {
        return "new method";
    }
}

测试代码

@Test
public void test11() {
    ApplicationContext app = new ClassPathXmlApplicationContext("di10.xml");
    MyValueCalculator myValueCalculator = app.getBean("myValueCalculator", MyValueCalculator.class);
    System.out.println(myValueCalculator.computeValue("input"));
}

运行结果如下:

在配置文件中,设置了myValueCalculator类中的computeValue方法,由replacementComputeValue的方法替换,最终调用的是replacementComputeValue的reimplement方法,输出new method。

你可能感兴趣的:(spring,java)