spring提供的三种注入方式:设置注入、构造注入、注解注入
先上spring的配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<!-- 打开aop自动扫描管理器 -->
<aop:aspectj-autoproxy/>
<!-- 打开组件自动扫描管理器 --><!-- 扫描cn.zzbj下的组件 -->
<context:component-scan base-package="cn.zzbj"/>
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${driverClassName}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
<!-- 连接池启动时的初始值 -->
<property name="initialSize" value="${initialSize}"/>
<!-- 连接池的最大值 -->
<property name="maxActive" value="${maxActive}"/>
<!-- 最大空闲值,当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 -->
<property name="maxIdle" value="${maxIdle}"/>
<!-- 最小空闲值,当空闲的连接数少于阀值时,连接池就会预申请一些连接,以免高峰期来不及申请 -->
<property name="minIdle" value="${minIdle}"/>
</bean>
<!-- 声明定义事务管理器 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 打开事物管理器注解标签 -->
<tx:annotation-driven transaction-manager="txManager"/>
</beans>
package cn.zzbj.service.impl;
import java.util.List;
import javax.annotation.Resource;
import javax.sql.DataSource;
import org.springframework.context.annotation.Scope;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import cn.zzbj.entity.Person;
import cn.zzbj.service.PersonService;
@Service("personService") @Scope("prototype") @Transactional
public class PersonServiceBean implements PersonService {
private DataSource dataSource;
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
@Transactional(rollbackFor=Exception.class)
@Override
public void save(Person person) {
System.out.println(jdbcTemplate==null);
jdbcTemplate.update("insert into person(name) values(?)", new Object[]{person.getName()},
new int[]{java.sql.Types.VARCHAR});
//throw new RuntimeException();
}
@Transactional(rollbackFor=Exception.class)
@Override
public void update(Person person) {
//测试datasource
System.out.println(dataSource);
}
@Transactional(rollbackFor=Exception.class)
@Override
public void delete(Integer id) {
// TODO Auto-generated method stub
}
@Transactional(propagation=Propagation.NOT_SUPPORTED)
@Override
public Person getPerson(Integer id) {
// TODO Auto-generated method stub
return null;
}
@Transactional(propagation=Propagation.NOT_SUPPORTED)
@Override
public List<Person> getPersons() {
// TODO Auto-generated method stub
return null;
}
}
@Test
public void test() {
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
PersonService ps = (PersonService) ac.getBean("personService");
try {
ps.update(new Person("aa"));
} catch (Exception e) {
e.printStackTrace();
}
}
问:配置文件中已经有了dataSource的bean了,这里采用了setter注入方式,但是没有dataSource的值是null,如果给属性dataSource添加上@Resource注解结果就不为null,setter方法中加上this.dataSource=dataSource;结果还是一样为null。
而使用上述粘贴的代码测试save()方法的时候报错:
java.lang.NullPointerException at cn.zzbj.service.impl.PersonServiceBean.save(PersonServiceBean.java:31) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) at com.sun.proxy.$Proxy11.save(Unknown Source) at cn.zzbj.test.ServiceTest.test(ServiceTest.java:24) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) at org.junit.runners.ParentRunner.run(ParentRunner.java:309) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
1.最初的配置是service的属性dataSource不加@Resource注解,结果dataSource为空容易理解,这就是一个普通属性,你么有初始化值
2.你在dataSource属性上加注解<aclass='referer'target='_blank'>@Resource,那么就是初始话了dataSource,这时dataSource不为空,但是dataSource有值不是调用setDataSource方法的(你可以看你的方法setDataSource你是没有设置dataSource的传入值)
3.<aclass='referer'target='_blank'>@Resource注解是写在属性上,不是方法上的,所以写在方法上是没效的,所以dataSource为空
4.第二种方法的dataSource虽然不为空,但是这个service没有构造JdbcTemplate,因为@Resource注解没有调用setDataSource()方法
解决办法:
在xml配置该service的bean,这样配置才会调用setDataSource()方法初始化JdbcTemplate,(这时service的dataSource为空,因为你没有this.dataSource=dataSource)
初始化了JdbcTemplate,你调用save才不会报空异常
如果你是想使用注解方法,请将JdbcTemplate也当成是一个全局bean,使用@Resource调用,如果不是,每个service你都需要构造或者加一个BaseSservice,所有service都继承
classclassBaseSservice{
@Resource
privateDataSourcedataSource;
privateJdbcTemplatejdbcTemplate;
@ModelAttribute
protectedvoidinitService(){
jdbcTemplate=newJdbcTemplate(this.dataSource);
}
}
<preclass="brush:java;toolbar:true;auto-links:false;">@Service("personService")@Scope("prototype")@TransactionalpublicclassPersonServiceBeanimplementsPersonService{privateDataSourcedataSource;privateJdbcTemplatejdbcTemplate;publicvoidsetDataSource(DataSourcedataSource){this.jdbcTemplate=newJdbcTemplate(dataSource);}
这里只是说PersonServiceBean是一个需要spring管理的bean,bean的id为persionService。
bean为prototype方式管理。
bean有事物。
你也没有配置让spring给你注入datasoure啊。在datasource上添加注解,spring才会知道你需要注入这个属性。
http://www.zhanghenglei.com/spring-injection-with-resource-autowired-and-inject/
<spanstyle="font-family:微软雅黑,Verdana,sans-serif,宋体;font-size:14px;line-height:22px;background-color:#FFFFFF;">配置文件中已经有了dataSource的bean了,这里采用了setter注入方式。。。。
<spanstyle="font-size:14px;line-height:22px;background-color:#FFFFFF;">如果用setter方式的话,<spanstyle="font-family:Consolas,'BitstreamVeraSansMono','CourierNew',Courier,monospace;font-size:14px;line-height:15.3999996185303px;background-color:#FFFFFF;">PersonServiceBean应该也配置在xml中,并且property其中一个为dataSource
<spanstyle="font-size:14px;line-height:22px;background-color:#FFFFFF;">要么全部用注解,要么全部用xml配置。不然出一堆问题搞死自己啊。
你set注入的方式你还没搞懂,不是有set方法 然后就可以自动注入。其他人我没看,巴顿说的没错。<atarget='_blank'>@影非弦慢慢来恩,有点混乱了