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'>@影非弦慢慢来恩,有点混乱了版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。