简体   繁体   English

Spring将数据源bean注入或自动装配到类

[英]Spring injecting or autowiring datasource bean to class

this may be a very novice question, but I have searched and either I have a large gap in my understanding or am doing something incorrectly that I cannot figure out. 这可能是一个非常新手的问题,但是我进行了搜索,发现我的理解上有很大的差距,或者做错了一些我无法弄清楚的事情。

In my context file here is an excerpt 在我的上下文文件中,这是摘录

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

<bean id="myBeanOne" class="a.b.c.myBeanOne">
         <property name="dataSource" ref="dataSource" />
</bean>

Now in myBeanOne I have: 现在在myBeanOne中,我有:

private DataSource dataSource;

private JdbcTemplate jdbcTemplate;

@Autowired
public void setDataSource (DataSource dataSource) {
    this.jdbcTemplate = new JdbcTemplate(dataSource);
}

public void myMethod() {
    String sql = "'My generic SQL update query'";
    try {
        this.jdbcTemplate.update(sql);
    } catch (org.springframework.dao.EmptyResultDataAccessException ex) {
    }
    System.exit(0);
}

when I try to execute this on the line where setDataSource is invoked I get this error: 当我尝试在调用setDataSource的行上执行此操作时,出现以下错误:

ERROR org.springframework.integration.handler.LoggingHandler 
    org.springframework.integration.MessageHandlingException: 
       java.lang.NullPointerException

on the line: this.jdbcTemplate.update(sql); 在行上: this.jdbcTemplate.update(sql);

I have tried maybe ten different configurations to get this to work, but I cannot seem to do it. 我尝试了十种不同的配置来使其正常工作,但是我似乎无法做到。 Any assistance is appreciated, thank you. 感谢您的协助,谢谢。

Edit: as per Luiggi's comment: 编辑:根据Luiggi的评论:

//in yet another classes run method
myBeanOne bOne = SomeOtherClass.create();   //just returns new myBeanOne
bOne.myMethod();

Neither SomeOtherClass or this class are classified as beans in the context or have any presence in the context. SomeOtherClass或此类都不在上下文中被分类为bean或在上下文中没有任何存在。

I know that this is a very basic question but I am struggling with it. 我知道这是一个非常基本的问题,但我正在努力解决。

Thank you for your patience. 感谢您的耐心等待。

As noted in comments, the problem is that you're manually creating the bean instead of letting Spring container create it. 如注释中所述,问题在于您是在手动创建bean,而不是让Spring容器创建它。 Basically, you're doing this: 基本上,您正在执行以下操作:

new MyBeanOne()

So Spring container can't inject any of the fields you have configured thus being null eg jdbcTemplate field. 因此,Spring容器无法注入您已配置的任何字段,因此为null例如jdbcTemplate字段。 There are some solutions to this: 有一些解决方案:

  1. Convert your SomeOtherClass into a bean managed by Spring container and let it inject the MyBeanOne instance (probably using @Autowired annotation). 将您的SomeOtherClass转换为由Spring容器管理的bean,并使其注入MyBeanOne实例(可能使用@Autowired批注)。

  2. If latter approach can't be done since you need to manually create the bean, you can create the bean manually as shown here: How to create spring beans dynamically? 如果由于需要手动创建Bean而无法使用后一种方法,则可以如下所示手动创建Bean: 如何动态创建Spring Bean?

    But this implementation makes you hardcode somewhere the spring config file name and use it in your code. 但是这种实现使您可以在spring config文件名的某处进行硬编码 ,并在代码中使用它。 So, a better approach would be option 3. 因此,更好的方法是选择3。

  3. Look at this solution: Creating New Spring Beans on Demand , where you create a client abstract class with a method that Spring will implement to retrieve a new instance of your Spring managed bean. 查看以下解决方案: 创建新的按需Spring Bean ,在其中创建客户端抽象类,该类具有Spring将实现的方法来检索Spring托管bean的新实例。


I found another way to handle this by using @Configurable annotation. 我发现了另一种使用@Configurable注释的方法。 By decorating your bean with this annotation, you can create a new instance of the bean on demand and Spring will manage the injection of Spring managed beans for you. 通过使用此批注装饰Bean,可以按需创建Bean的新实例,Spring将为您管理Spring托管Bean的注入。 But to achieve this, Spring needs to use aspects behind the scenes and you should activate usage of aspects for your project. 但是要实现这一点,Spring需要在幕后使用方面,而您应该为项目激活方面的使用。 The explanation is quite long, so I provide links that explain in depth this solution: 解释很长,因此我提供了深入解释此解决方案的链接:

Note that in order to enable this feature , you have to add a java agent when starting the JVM that will weave the class at runtime using aspects. 请注意,为了启用此功能 ,您必须在启动JVM时添加Java代理该Java代理将在运行时使用方面来编织类。

NullPointerException on the line: this.jdbcTemplate.update(sql); 行上的NullPointerException :this.jdbcTemplate.update(sql);

If the NPE is actually on that line, then this.jdbcTemplate is obviously null . 如果NPE实际上在那条线上,则this.jdbcTemplate显然为null If this is true then either: 如果是这样,则可以:

  • The setDataSource(...) method is not being called in Spring, possibly because the @Autowired is not right somehow. 在Spring中没有调用setDataSource(...)方法,可能是因为@Autowired不正确。 It would be easy to add a System.out.println(...) or put a debugging breakpoint in setDataSource to see if it is being called. 添加System.out.println(...)或在setDataSource放置调试断点以查看是否被调用将很容易。

  • If it is being called then maybe there are more than one instance of abcmyBeanOne ? 如果称之为话,说不定也有多个实例abcmyBeanOne Are you for sure getting the instance being called from another class from the Spring context? 您确定要从Spring上下文的另一个类中调用该实例吗? Put a breakpoint in setDataSource and notice the this object reference id. setDataSource放置一个断点,并注意this对象引用ID。 Then put a breakpoint on the this.jdbcTemplate.update(...) line and make sure that the this reference-id is the same. 然后在this.jdbcTemplate.update(...)行上放置一个断点,并确保this引用ID相同。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM