Почему мое поле Spring @Autowired равно null?
Примечание: это должно быть каноническим ответом на общую проблему.
у меня есть пружина @Service класса (MileageFeeCalculator), имеющего 
12 ответов
поле аннотированный @Autowired is null потому что весна не знает о копия MileageFeeCalculator С new и не знал, чтобы autowire его.
пружинная инверсия контейнера управления (IoC) имеет три основных логических компонента: реестр (называемый ApplicationContext) компонентов (компонентов), которые доступны для использования приложением, системой конфигуратора, которая вводит в них зависимости объектов путем сопоставления зависимостей с бобы в контексте и решатель зависимостей, который может просматривать конфигурацию многих разных бобов и определять, как создавать экземпляры и настраивать их в необходимом порядке.
контейнер IoC не волшебный, и он не может знать об объектах Java, если вы каким-то образом не сообщите ему о них. Когда вы звоните new, JVM создает экземпляр нового объекта и передает его прямо вам-он никогда не проходит процесс настройки. Есть три способа, которыми вы можете настройте свои бобы.
я написал весь этот код, используя Spring Boot для запуска, в этот проект GitHub; вы можете посмотреть на полный запуск проекта для каждого подхода, чтобы увидеть все, что вам нужно, чтобы заставить его работать. тега NullPointerException: nonworking
ввести свой зерен
самый предпочтительный вариант-позволить Spring autowire всем вашим бобам; это требует наименьшего количества кода и является самый обслуживаемый. Чтобы заставить autowiring работать так, как вы хотели, также autowire MileageFeeCalculator такой:
@Controller
public class MileageFeeController {
    @Autowired
    private MileageFeeCalculator calc;
    @RequestMapping("/mileage/{miles}")
    @ResponseBody
    public float mileageFee(@PathVariable int miles) {
        return calc.mileageCharge(miles);
    }
}
Если вам нужно создать новый экземпляр объекта службы для разных запросов, вы все равно можете использовать инъекцию с помощью область весенних бобов.
тег, который работает путем инъекций @MileageFeeCalculator сервис объекта: working-inject-bean
Использовать @Настраиваемые!--42-->
Если вам действительно нужно объекты, созданные с помощью new чтобы быть autowired, вы можете использовать весной @Configurable аннотация вместе с AspectJ время компиляции сотка для инъекции ваших объектов. Этот подход вставляет код в конструктор объекта, который предупреждает Spring о его создании, чтобы Spring мог настроить новый экземпляр. Это требует немного конфигурации в вашей сборке (например, компиляции с помощью ajc) и включение обработчиков конфигурации среды выполнения Spring (@EnableSpringConfigured С JavaConfig синтаксис.) Этот подход используется системой активной записи Roo, чтобы разрешить 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 может autowire, и устаревший код могут вызывать, но можно напрямую запросить контекст приложения Spring для компонента.
для этого вам нужен класс, к которому Spring может дать ссылку на
Если вы не кодируете веб-приложение, убедитесь, что ваш класс, в котором выполняется @Autowiring, является spring bean. Как правило, Spring container не будет знать о классе, который мы могли бы подумать как spring bean. Мы должны рассказать весеннему контейнеру о наших весенних классах.
Это может быть достигнуто путем настройки в appln-contxt или лучше аннотировать класс как @Component и, пожалуйста, не создавайте аннотированный класс с помощью new оператор. Убедитесь, что вы получаете его из Appln-контекста, как показано ниже.
@Component
public class MyDemo {
    @Autowired
    private MyService  myService; 
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
            System.out.println("test");
            ApplicationContext ctx=new ClassPathXmlApplicationContext("spring.xml");
            System.out.println("ctx>>"+ctx);
            Customer c1=null;
            MyDemo myDemo=ctx.getBean(MyDemo.class);
            System.out.println(myDemo);
            myDemo.callService(ctx);
    }
    public void callService(ApplicationContext ctx) {
        // TODO Auto-generated method stub
        System.out.println("---callService---");
        System.out.println(myService);
        myService.callMydao();
    }
}
На самом деле для вызова методов следует использовать управляемые объекты JVM или Spring-managed Object. из приведенного выше кода в классе контроллера создается новый объект для вызова класса обслуживания, который имеет объект auto-wired.
MileageFeeCalculator calc = new MileageFeeCalculator();
Так что это не сработает.
решение делает этот MileageFeeCalculator как авто-проводной объект в самом контроллере.
изменить ваш класс контроллера, как показано ниже.
@Controller
public class MileageFeeController {
    @Autowired
    MileageFeeCalculator calc;  
    @RequestMapping("/mileage/{miles}")
    @ResponseBody
    public float mileageFee(@PathVariable int miles) {
        return calc.mileageCharge(miles);
    }
}
Я однажды столкнулся с той же проблемой, когда я не совсем привык к the life in the IoC world. The @Autowired поле одного из моих бобов равно null во время выполнения.
основная причина заключается в том, вместо использования автоматически созданного компонента, поддерживаемого контейнером Spring IoC (чей
ваша проблема новая (создание объекта в стиле java)
MileageFeeCalculator calc = new MileageFeeCalculator();
аннотации @Service, @Component, @Configuration бобы создаются в
    контекст приложения Spring при запуске сервера. Но когда мы создаем объекты 
    с помощью оператора new объект не регистрируется в уже созданном контексте приложения. Например, Сотрудник.класс java, который я использовал.
зацени вот это:
public class ConfiguredTenantScopedBeanProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    String name = "tenant";
    System.out.println("Bean factory post processor is initialized"); 
    beanFactory.registerScope("employee", new Employee());
    Assert.state(beanFactory instanceof BeanDefinitionRegistry,
            "BeanFactory was not a BeanDefinitionRegistry, so CustomScope cannot be used.");
    BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
    for (String beanName : beanFactory.getBeanDefinitionNames()) {
        BeanDefinition definition = beanFactory.getBeanDefinition(beanName);
        if (name.equals(definition.getScope())) {
            BeanDefinitionHolder proxyHolder = ScopedProxyUtils.createScopedProxy(new BeanDefinitionHolder(definition, beanName), registry, true);
            registry.registerBeanDefinition(beanName, proxyHolder.getBeanDefinition());
        }
    }
}
}
это, кажется, редкий случай, но вот что случилось со мной:
мы @Inject вместо @Autowired который является стандартом javaee, поддерживаемым весной. В каждом месте он работал нормально, и бобы вводились правильно, а не в одном месте. Инъекция бобов кажется такой же
@Inject
Calculator myCalculator
наконец мы обнаружили, что ошибка заключалась в том, что мы (на самом деле, функция автоматического завершения Eclipse) импортировали com.opensymphony.xwork2.Inject вместо javax.inject.Inject !
Итак, убедитесь, что ваш Примечания (@Autowired, @Inject, @Service ,... ) имейте правильные пакеты!
Я новичок в Spring, но я обнаружил это рабочее решение. Пожалуйста, скажите мне, если это deprecable пути.
Я делаю весенний укол applicationContext в этой фасоли:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
@Component
public class SpringUtils {
    public static ApplicationContext ctx;
    /**
     * Make Spring inject the application context
     * and save it on a static variable,
     * so that it can be accessed from any point in the application. 
     */
    @Autowired
    private void setApplicationContext(ApplicationContext applicationContext) {
        ctx = applicationContext;       
    }
}
вы можете поместить этот код в главный класс приложения, если вы хотите.
другие классы могут использовать его следующим образом:
MyBean myBean = (MyBean)SpringUtils.ctx.getBean(MyBean.class);
таким образом любой Боб может быть получен любым объектом в приложении (также intantiated с new) и статически.
Я думаю, вы пропустили, чтобы поручить spring сканировать классы с аннотациями.
можно использовать @ComponentScan("packageToScan") в классе конфигурации вашего приложения spring, чтобы указать spring для сканирования.
@Service, @Component etc аннотации добавить мета-описание.
Spring только вводит экземпляры тех классов, которые либо созданы как bean, либо отмечены аннотациями.
классы, отмеченные аннотацией, должны быть идентифицированы весной до инъекции,@ComponentScan поручить spring искать классы, отмеченные аннотацией. Когда весна найдет @Autowired он ищет связанный компонент и вводит требуемый экземпляр.
добавление аннотации только, не исправляет или не облегчает инъекцию зависимостей, весна должна знать, где искать.
другое решение было бы положить вызов:
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this)
Для mileagefeecalculator конструктора, как это:
@Service
public class MileageFeeCalculator {
    @Autowired
    private MileageRateService rateService; // <--- will be autowired when constructor is called
    public MileageFeeCalculator() {
        SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this)
    }
    public float mileageCharge(final int miles) {
        return (miles * rateService.ratePerMile()); 
    }
}
вы также можете исправить эту проблему, используя аннотацию @Service в классе обслуживания и передавая требуемый класс bean в качестве параметра другому конструктору класса beans classB и аннотировать конструктор classB с помощью @Autowired. Пример фрагмента здесь:
@Service
public class ClassB {
    private ClassA classA;
    @Autowired
    public ClassB(ClassA classA) {
        this.classA = classA;
    }
    public void useClassAObjectHere(){
        classA.callMethodOnObjectA();
    }
}
обновление: действительно умные люди быстро указали на этой ответ, который объясняет странность, описанную ниже
ОРИГИНАЛЬНЫЙ ОТВЕТ:
Я не знаю, помогает ли это кому-нибудь, но я застрял с той же проблемой, даже делая вещи, казалось бы, правильно. В моем основном методе у меня есть такой код:
ApplicationContext context =
    new ClassPathXmlApplicationContext(new String[] {
        "common.xml",
        "token.xml",
        "pep-config.xml" });
    TokenInitializer ti = context.getBean(TokenInitializer.class);
и token.xml файл у меня была строка
<context:component-scan base-package="package.path"/>
я заметил, что пакет.путь больше не существует, поэтому я просто отбросил линию навсегда.
и после этого, NPE начал приходить. В pep-config.xml у меня было всего 2 боба:
<bean id="someAbac" class="com.pep.SomeAbac" init-method="init"/>
<bean id="settings" class="com.pep.Settings"/>
и класс SomeAbac имеет свойство, объявленное как
@Autowired private Settings settings;
по какой-то неизвестной причине настройки null в init(), когда <context:component-scan/> элемент отсутствует вообще, но когда он присутствует и имеет некоторые bs в качестве базового пакета, все работает хорошо. Эта линия теперь выглядит так: 
<context:component-scan base-package="some.shit"/>
и это работает. Может быть кто-то может дать объяснение, но для меня этого достаточно сейчас )
Если это происходит в тестовом классе, убедитесь, что вы не забыли аннотировать класс.
например,Весна Загрузки:
@RunWith(SpringRunner.class)
@SpringBootTest
public class MyTests {
    ....
