web-dev-qa-db-ja.com

Spring @ Autowiredが機能しない

自動配線注釈に問題があります。私のアプリは次のようになります:

これがコントローラーです:

@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 Autowiresは正しく(someServiceImplクラスオブジェクトによって正しく挿入されたsomeServiceフィールド)、someServiceのmyDAOフィールドにはnull値があります(正しく挿入されていません)。

問題を見つけるのを手伝ってくれませんか。

P.S.興味深いですが、「Bean ID」をmyDAOから別のID(myDAO2など)に変更すると、Bean myDAOが存在しないため、システムにエラーが表示され、注入を実行できませんでした。それで、春は注射をします、しかしそれはどこにありますか?そして、なぜそれが正しく機能しないのですか?

9
Ilnur

私は解決策を見つけました。 Javiが言ったように(Javiさん、どうもありがとうございました)、DAOおよびサービスレイヤークラスに@Repositoryおよび@Serviceアノテーションを付ける必要があります。今、私はこのように書こうとしました:

@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アノテーション付き)?

10
Ilnur

<context:annotation-config />が必要だと思います。

4
axtavt

あなたが使用することができます

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

構成.xmlファイルのエントリ。このエントリは、Javaクラスから指定されたすべてのタイプと注釈をスキャン/読み取ります。

重要なポイント:

  1. @Componentは、デフォルトのコンストラクターが見つからないと言う問題を引き起こす場合があります。 @Componentアノテーションとして定義されているクラスには、デフォルトのコンストラクターが必要です。
  2. ユーザー定義のクラス参照であるフィールドに@Autowiredアノテーションを適用したとします。ここで、@ Componentもそのクラスに適用すると、常にnullで初期化されます。したがって、@ Autowiredを含むフィールドでは、クラス定義に@Componentを含めるべきではありません。
  3. デフォルトでは、@ 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();
    }
}

Elgin通りを学生の住所で自動配線する必要があります。

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);
    }
}

出力:-名前:null年齢:0アドレス:null //アドレスはここで自動配線されていません。

この問題を解決するには、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);
    }
}

出力:-名前:null年齢:0住所:Elginstreet

1
Sumit Basu