Spring@Autowired不工作

pgpifvop  于 2023-09-29  发布在  Spring
关注(0)|答案(8)|浏览(91)

我有一些问题与autowire注解。我的app看起来像这样:
这里是控制器:

@Controller
public class MyController {
    @Autowired
    @Qualifier("someService")
    private SomeService someService;

    ....
}

它是一个服务层:

public interface SomeService {
    ...
}

@Service
public class SomeServiceImpl implements SomeService{    
    @Autowired
    @Qualifier("myDAO")
    private MyDAO myDAO;

    ....
}

DAO层:

public interface MyDAO{
    ....        
}

@Repository
public class JDBCDAOImpl implements MyDAO {    
    @Autowired
    @Qualifier("dataSource")
    private DataSource dataSource;    
    ....
}

这是一个app-service.xml文件:

....
<bean id="propertyConfigurer"
      class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
      p:location="/WEB-INF/jdbc.properties" />

<bean id="dataSource"
      class="org.springframework.jdbc.datasource.DriverManagerDataSource"
      p:driverClassName="${jdbc.driverClassName}"
      p:url="${jdbc.url}"
      p:username="${jdbc.username}"
      p:password="${jdbc.password}"/>

<bean id="SomeService" class="com.service.SomeServiceImpl" />    
<bean id="myDAO" class="com.db.JDBCDAOImpl" />

所以...当我启动一个web应用程序时,MyController自动连接正确(SomeServiceImpl类对象正确注入的someService字段),但someService的myDAO字段具有空值(未正确注入)。
你能帮我找一个问题吗?
P.S.这很有趣,但是当我将一个“bean id”从myDAO更改为另一个(例如:myDAO 2),系统给了我一个错误,注入无法完成,因为beanmyDAO不存在。所以,Spring打了一针,但它在哪里?为什么不能正常工作?

svgewumm

svgewumm1#

我找到解决办法了。正如Javi所说(非常感谢你,Javi),我必须用@Repository@Service注解来注解DAO和服务层类。我试着这样写:

@Service("someService")
public class SomeServiceImpl implements SomeService{    
    @Autowired
    @Qualifier("myDAO")
    private MyDAO myDAO;

    ....
}

@Repository("myDAO")
    public class JDBCDAOImpl implements MyDAO {    
    @Autowired
    @Qualifier("dataSource")
    private DataSource dataSource;    
    ....
}

一切正常!!!
但我仍然没有找到这个问题的答案:如果应用程序将更复杂,并将具有更复杂的结构,其中@Repositore@Service注解对于某些类来说不是首选的,那么如何正确地注入位于较低级别(在类的字段中,或者在类的字段的字段中)的bean(当然,使用@Autowire注解)?

7gyucuyw

7gyucuyw2#

我猜你需要<context:annotation-config />

f1tvaqid

f1tvaqid3#

您可以使用

<context:component-scan base-package="PATH OF THE BASE PACKAGE"/>

在configuration.xml文件中输入。此条目将扫描/读取Java类中所有声明的类型和注解。

uinbv5nw

uinbv5nw4#

注意事项:
1.有时,@Component可能会导致一个问题,它可能会说没有找到默认的构造函数。定义为@Component注解的类必须有默认构造函数。
1.假设,我们在字段中应用了@Autowired注解,这是一个用户定义的类引用。现在,如果我们也将@Component应用于该类,那么它将始终使用null初始化。因此,带有@Autowired的字段不应在其类定义中包含@Component。
1.默认情况下,@Autowired是byType。
地址bean在Student类中自动连接。让我们看看如果在Address.java中应用@Component会发生什么。
网址:CollegeApp.java

package com.myTest
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import com.bean.Address;
import com.bean.Student;
//Component scanning will for only those classes
//which is defined as @Component. But, all the class should not use
//@Component always even if the class is enabled with auto
//component scanning, specially the class which is Autowired
//Or which is a property of another class 
@Configuration
@ComponentScan(basePackages={"com.bean"})
public class CollegeApp {
    @Bean
    public Address getAddress(){
        return new Address("Elgin street");
}
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(CollegeApp.class);
        Student student=context.getBean(Student.class);
        System.out.println(student.toString());
        context.close();
    }
}

我们希望埃尔金街能自动连接上学生地址。
网址:Address.java

package com.bean;
import org.springframework.stereotype.Component;
@Component
public class Address {
    private String street;
    public Address()
    {
    }
    public Address(String theStreet)
    {
        street=theStreet;
    }
    public String toString()
    {
        return (" Address:"+street);
    }
}

网址:Student.java

package com.bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Student {
    private String name;
    private int age;
    private Address address;
    public Student()
    {
    }
    public Student(String theName,int theAge)
    {
        name=theName;age=theAge;
    }
    @Autowired
    public void setAddress(Address address) {
        this.address = address;
    }
    public String toString()
    {
        return ("Name:"+name+" Age:"+age+ " "+address);
    }
}

Output:- Name:null Age:0 Address:null //Address not Autowired here.
要解决此问题,只需更改Address.java,如下所示:
网址:Address.java

package com.bean;
public class Address {
    private String street;
    public Address(String theStreet)
    {
        street=theStreet;
    }
    public String toString()
    {
        return (" Address:"+street);
    }
}

Output:- Name:null年龄:0地址:埃尔金street

np8igboo

np8igboo5#

您应该在spring-config.xml中包含这段XML代码:

<context:component-scan base-package="Fully.Qualified.Package.Name" />

但是你应该知道<context:annotation-config><context:component-scan>之间的区别,因为大多数人都建议这两个:
1)两个标记之间的第一个大区别<context:annotation-config>用于激活应用程序上下文中已注册的bean中的应用注解。请注意,bean是否通过哪种机制注册并不重要,例如使用<context:component-scan>或在application-context.xml文件本身中定义。
2)第二差异由第一差异本身驱动。它在上下文中注册bean+它还扫描bean内部的注解并激活它们。所以<context:component-scan>; <context:annotation-config>所做的事情,但它还扫描包并在应用程序上下文中注册bean。

anhgbhbe

anhgbhbe6#

这可能有两个原因。
1.当您没有注解注入的对象或使用适当的@Service/@Component/@Repository注解表示service时。
1.一旦你确定了第1点,接下来检查你注解的service class的class package是否包含在main class中spring Boot application的class-path中。你可以使用下面的annotation来配置。
@SpringBootApplication(scanBasePackages = {“com.ie.efgh.somepackage”,“com.ie.abcd. somotherpackage”})
这样做的时候,你告诉spring在类加载的时候查看类的包。

nbewdwxp

nbewdwxp7#

我的问题是,当我想获取单元测试时,我在Application的入口点添加@ComponentScan,并为class添加@Component来标记它,以便Spring可以在上下文中创建bean,但仍然不能运行,最终我忘记用

@SpringBootTest

所以应该

@SpringBootTest
class FluxDemoTest {

    @Autowired
    private FluxDemo fluxDemo;

    @Test
    public void testFlux() {

        StepVerifier.create(fluxDemo.list_Integer()).expectNextCount(6).verifyComplete();
    }

}
rsl1atfo

rsl1atfo8#

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- Specifying base package of the Components like Controller, Service, 
        DAO -->
    <context:component-scan base-package="com.jwt" />

    <!-- Getting Database properties -->
    <context:property-placeholder location="classpath:application.properties" />

    <!-- DataSource -->
    <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"
        id="dataSource">
        <property name="driverClassName" value="${database.driver}"></property>
        <property name="url" value="${database.url}"></property>
        <property name="username" value="${database.user}"></property>
        <property name="password" value="${database.password}"></property>
    </bean>

    <!-- Hibernate SessionFactory -->
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
                <prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
                <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
            </props>
        </property>
    </bean>

</beans>

相关问题