2017-07-14 17 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 –

相关问题