2017-07-14 16 views
0

其實我有一個如下的spring主類。當類對象是新的時,無法使用@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來爲空。任何人都可以給我一些解決方案,因爲我也知道新的運營商不會爲@autowired工作。當我用新實例加載類時,只有它變爲空。任何人都可以引導我在這個東西

+0

不要使用新的運營商,並注入在你需要它的特定類。如果您想在Spring Boot應用程序啓動後立即運行某些內容,請查看ApplicationRunner接口。 – dunni

+0

@dunni - 其實我正在使用java反射來加載類,其中我必須創建新的實例。所以,它使新的實例和自動裝配fd null。這個代碼對我們來說就像一個例子。 –

+0

然後,你應該發佈一個例子,更好地反映你的情況。 – dunni

回答

0

春天有自己的方式爲您提供新的對象。只要你一致使用@Autowired@Component/@Service/@Repository/@Controller應該沒有問題

並且由於所有「業務」對象實例化由Spring處理,因此不應使用new。如果您沒有其他方式獲得實例(我真的懷疑它),您可以使用ApplicationContext.getBean(),但正如我所說的,在大多數情況下,這不是必需的(這也是一個不好的做法)

如果您需要一類,而不是注入其中的幾個實例(通過使用@Autowired),你可以注入一個Provider<T>

UPDATE

由於類是在運行時知道你需要注入一個ApplicationContext,並用它來獲取豆:

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'。如果您在編譯時知道哪種對象會使用第一種方法(它更安全)。如果在運行時已知對象的類型(可能性很大),請使用第二種方法 – 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 –

相關問題