2017-07-14 6 views
0

実際に私は次のように春のメインクラスを持っています。クラスオブジェクトが新しくなったとき@springアノテーションを使用できません

ClassLoader loader = null; 

    try { 
     loader = URLClassLoader.newInstance(new URL[]{new 

File(plugins + "/" + pluginName + "/" + pluginName + 

".jar").toURI().toURL()}, getClass().getClassLoader()); 

    } catch (MalformedURLException e) { 
     e.printStackTrace(); 
    } 

Class<?> clazz = null; 

    try { 

     clazz = Class.forName("com.sample.Specific", true, loader); 

    } catch (ClassNotFoundException e) { 

     e.printStackTrace(); 

    } 

Method method = null; 
    try { 
     method = clazz.getMethod("run",new Class[]{}); 
    } catch (NoSuchMethodException e) { 
     e.printStackTrace(); 
    } 

try { 
     method.invoke(clazz.newinstance,new Object[]{}); 
    } catch (IllegalAccessException e) { 
     e.printStackTrace(); 
    } catch (InvocationTargetException e) { 
     e.printStackTrace(); 
    } 

特定のクラスは以下の通りです:

package com.sample 
@Service 
public class Specific { 

    @Autowired 
    private FD fd; 


    public void run(){ 

     fd.init(); 

    } 

} 

@AutowiredFDはnullにしています。誰も私には、新しい演算子は@autowiredのために動作しません知っているように私にいくつかの解決策を与えることができます。私は新しいインスタンスでクラスをロードしているので、nullだけになります。誰でもこのことで私を導くことができます

+0

は、new演算子を使用し、あなたがそれを必要とする特定のクラスを注入しないでください。 Spring起動アプリケーションを起動した直後に何かを実行したい場合は、 'ApplicationRunner'インタフェースを見てください。 – dunni

+0

@dunni - 実際には、私は新しいインスタンスを作成する必要があるJavaのリフレクションを使用してクラスをロードしています。したがって、新しいインスタンスを作成し、autowired fdをnullにします。このコードは、私たちのための例のように動作します。 –

+0

あなたの状況をよりよく反映した例を投稿してください。 – dunni

答えて

0

春には新しいオブジェクトを提供する独自の方法があります。 @Autowired@Component/@Service/@Repository/@Controllerを使用して一貫している限り、問題はありません。

そして、すべての "ビジネス"オブジェクトインスタンシエーションはSpringによって処理されるので、決してnewを使うべきではありません。私が言ったように、これは必須ではありません(これは悪い習慣でもあります)。

もし必要ならばクラスは、実行時に知られているので、あなたがApplicationContextを注入し、Beanを取得するためにそれを使用する必要がありますProvider<T>

UPDATE

を注入することができます(@Autowiredを使用して)の代わりにそれらを注入するクラスの複数のインスタンス:

public class TheClassWhereYouAreCreatingTheObject { 

    @Autowired 
    private ApplicationContext context;     // You definitely need this 

    public void theMethodWhereYouAreCreatingTheObject() { 
     Class<?> clazz = ...       // getting the object class 
     Object instance = context.getBean(clazz);  // getting and instance trough Spring 

     // If you know that kind of object you will get cast it at call its methods 
     ((Specific) instance).run(); 

     // If you know anything about the class you will have to use reflection 
     Method method = clazz.getMethod("run", new Class[]{}); 
     method.invoke(instance, new Object[]{}); 
    } 
} 
+0

あなたの提案に感謝@Pelocho。私は春のブートで実行時にクラスをロードするので、私はまた、そのフィールドを取得することはできません。だから、クラスをロードする他の方法はありません –

+0

私は上の更新された例を見たと思います。ありがとう –

+0

実行時にインスタンスを「作成」する場合は、 'Provider'を使うか、' applicationContext'を注入することを検討してください。コンパイル時に、どのようなオブジェクトを使用するのかを知っている場合は、最初のアプローチを使用します(もっと安全です)。オブジェクトの種類が実行時にわかっている(そして可能性が高い)場合は、2番目の方法を使用してください – Pelocho

0

メインクラスの中に特定サービスBeanを追加してください。サービスがあなたのコンポーネントスキャンパッケージの中にある限り、あなたは大丈夫でしょう。新しい演算子は使用しないでください。

@Autowired 
private Specific specific; 
+0

私は同意しますが、今私は具体的な問題の例を変更しました。あなたはこの中で私を助けることができます –

+0

あなたの助けをありがとう。この質問で私を助けてくれますか?これはまた、このような同じ問題ですhttps://stackoverflow.com/questions/45115102/how-to-create-a-bean-at-runtime-at-the-time-while-using-class-loading-java- refl –

0

オートワイヤリングを利用したい場合は、春期から考えなければならないと思います。

Beanutilsを使用すると、新しいインスタンスを作成し、春の機能をサポートするリフレクションで再生できます。 方法の下に通過してください:

https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/BeanUtils.html

+0

ありがとうございました。この質問で私を助けてください。それは同じ問題に関連していますhttps://stackoverflow.com/questions/45115102/how-to-create-a-bean-at-runtime-at-the-time-while-using-class-loading-java-refl –

関連する問題