带@Autowired的字段为null是因为Spring不知道你创建了对象。
Spring Inversion of Control(IoC)容器具有三个主要的逻辑组件:
1.ApplicationContext注册表,
2. 配置器系统通过匹配对象将对象的依赖项注入到它们中在上下文中具有bean的依赖关系
3.一个依赖关系解决程序,它可以查看许多不同bean的配置并确定如何以必要的顺序实例化和配置它们。
IoC容器没有魔力,除非您以某种方式告知Java对象,否则它无法了解Java对象。当您调用时new,JVM实例化新对象的副本并将其直接交给您-它从未经历配置过程。您可以通过三种方式配置bean。
注入你的java bean
最可取的选择是让Spring自动连接所有bean。这需要最少的代码量,并且最易于维护。为了使自动装配工作如您所愿,还可以MileageFeeCalculator像这样自动装配:
@Controller
public class MileageFeeController {
@Autowired
private MileageFeeCalculator calc;
@RequestMapping("/mileage/{miles}")
@ResponseBody
public float mileageFee(@PathVariable int miles) {
return calc.mileageCharge(miles);
}
}
如果您需要为不同的请求创建服务对象的新实例,则仍然可以通过使用Spring bean scopes使用注入。
通过注入@MileageFeeCalculator服务对象起作用的标记:working-inject-bean
使用@Configurable
如果确实需要new自动创建的对象,则可以将Spring@Configurable注释与AspectJ编译时编织一起使用以注入对象。这种方法将代码插入到对象的构造函数中,以警告Spring正在创建它,以便Spring可以配置新实例。这需要在构建中进行一些配置(例如使用进行编译ajc)并打开Spring的运行时配置处理程序(@EnableSpringConfigured使用JavaConfig语法)。Roo Active Record系统使用此方法来允许new您的实体实例获取注入的必要持久性信息。
@Service
@Configurable
public class MileageFeeCalculator {
@Autowired
private MileageRateService rateService;
public float mileageCharge(final int miles) {
return (miles * rateService.ratePerMile());
}
}
通过@Configurable在服务对象上使用而起作用的标记:working-configurable
手动查找bean:不建议
这种方法仅适用于在特殊情况下与遗留代码接口。几乎总是最好创建一个Spring可以自动装配并且遗留代码可以调用的Singleton适配器类,但是可以直接向Spring应用程序上下文请求一个bean。
为此,您需要一个Spring可以引用该ApplicationContext对象的类:
@Component
public class ApplicationContextHolder implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static ApplicationContext getContext() {
return context;
}
}
然后,您的旧代码可以调用getContext()并检索所需的bean:
@Controller
public class MileageFeeController {
@RequestMapping("/mileage/{miles}")
@ResponseBody
public float mileageFee(@PathVariable int miles) {
MileageFeeCalculator calc = ApplicationContextHolder.getContext().getBean(MileageFeeCalculator.class);
return calc.mileageCharge(miles);
}
}