Spring自动装配(autowire)麻烦吗?
简单介绍一下Spring 中autowire(自动装配)那首先问问你,你觉得spring中autowire(自动装配)好吗?
如果使用它可能会降低可读性和可维护性,但是在spring中类与类之间的依赖都用<ref>标签来连接,这样太费事了。那你如何选择呢?
下面介绍Spring为我们提供了autowire(自动装配)的属性。
在spring配置文件中autowire属性值如下:
1:no解析
不使用自动装配,是autowire默认的值。必须通过ref元素指定依赖,这是默认设置。
案例:
//spring中 app.xml的设置
<!-- 定义一个empServiceImpl的javabean实例 -->
<bean id="empServiceImpl" class="com.csdn.service.EmpServiceImpl">
<property name="name">
<value>Nan</value></property>
</bean>
<!-- 定义一个hourEmpServiceImpl的javabean实例,实现empServiceImpl的业务层 -->
<bean id="hourEmpServiceImpl" class="com.csdn.service.HourEmpServiceImpl" autowire="no" >
<!—autowire的定义为no代表实现其它类时需要用ref -->
<property name="empServiceImpl" ref="empServiceImpl"></property>
</bean>
//empServiceImpl的代码
package com.csdn.service;
public class EmpServiceImpl {
/**定义一个变量实例*/
private String name;
/**通过set方法进行赋值*/
public void setName(String name) {
this.name = name;
}
}
// hourEmpServiceImpl的代码
package com.csdn.service;
public class HourEmpServiceImpl {
/**定义一个EmpServiceImpl的操作对象*/
private EmpServiceImpl empServiceImpl;
/**生成相应的set方法 通过set方法注入的*/
public void setEmpServiceImpl(EmpServiceImpl empServiceImpl) {
this.empServiceImpl = empServiceImpl;
}
}
//junit测试类代码
@Test
public void test(){
ApplicationContext ac = new ClassPathXmlApplicationContext("app.xml");
HourEmpServiceImpl hsi=(HourEmpServiceImpl) ac.getBean("hourEmpServiceImpl");
}
2:byName解析
通过属性名的方式查找spring容器,检测javabean的名字与属性完全一致的bean,并将其与属性自动装配。
案例:
//spring中 app.xml的设置
<!-- 定义一个empServiceImpl的javabean实例 -->
<bean id="empServiceImpl" class="com.csdn.service.EmpServiceImpl">
<property name="name">
<value>Nan</value></property>
</bean>
<!-- 定义一个hourEmpServiceImpl的javabean实例,实现empServiceImpl的业务层 -->
<bean id="hourEmpServiceImpl" class="com.csdn.service.HourEmpServiceImpl" autowire="byName" >
<!—autowire的定义为byName代表实现其它类,自动检测javabean的名字与属性完全一样的注意:如果实现的javabean没有在Spring的xml中实例,那么也不会报错只是为空值-->
</bean>
//empServiceImpl的代码
package com.csdn.service;
public class EmpServiceImpl {
/**定义一个变量实例*/
private String name;
/**通过set方法进行赋值*/
public void setName(String name) {
this.name = name;
}
}
// hourEmpServiceImpl的代码
package com.csdn.service;
public class HourEmpServiceImpl {
/**定义一个EmpServiceImpl的操作对象*/
private EmpServiceImpl empServiceImpl;
/**生成相应的set方法 通过set方法注入的*/
public void setEmpServiceImpl(EmpServiceImpl empServiceImpl) {
this.empServiceImpl = empServiceImpl;
}
}
//junit测试类代码
@Test
public void test(){
ApplicationContext ac = new ClassPathXmlApplicationContext("app.xml");
HourEmpServiceImpl hsi=(HourEmpServiceImpl) ac.getBean("hourEmpServiceImpl");
}
3:byType的解析
如果容器中存在一个与指定属性类型相同的bean,如果没有找到相符的bean,该属性就没有被装配上。如果存在多个该类型的bean,那么将会抛出异常,并指出不能使用byType方式进行自动装配。
案例:
//spring中 app.xml的设置
<!-- 定义一个empServiceImpl的javabean实例 -->
<bean id="empServiceImpl" class="com.csdn.service.EmpServiceImpl">
<property name="name">
<value>Nan</value></property>
</bean>
<!-- 定义一个HourAddressServiceImpl的javabean实例实现了EmpServiceImpl的javabean那么会出现bug:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'hourEmpServiceImpl' defined in class path resource [app.xml]: Unsatisfied dependency expressed through bean property 'empServiceImpl': : No unique bean of type [com.csdn.service.EmpServiceImpl] is defined: expected single matching bean but found 2: [empServiceImpl, com.csdn.service.HourAddressServiceImpl#0]; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.csdn.service.EmpServiceImpl] is defined: expected single matching bean but found 2: [empServiceImpl, com.csdn.service.HourAddressServiceImpl#0]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByType(AbstractAutowireCapableBeanFactory.java:1091)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:982)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:472)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
at java.security.AccessController.doPrivileged(Native Method)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:429)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:728)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:380)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at com.csdn.junit.EmpTest.test(EmpTest.java:13)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:73)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:46)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:180)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:41)
at org.junit.runners.ParentRunner$1.evaluate(ParentRunner.java:173)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.ParentRunner.run(ParentRunner.java:220)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.csdn.service.EmpServiceImpl] is defined: expected single matching bean but found 2: [empServiceImpl, com.csdn.service.HourAddressServiceImpl#0]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:621)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByType(AbstractAutowireCapableBeanFactory.java:1076)
... 40 more
<bean class="com.csdn.service.HourAddressServiceImpl"></bean>
-->
<!-- 定义一个hourEmpServiceImpl的javabean实例,实现empServiceImpl的业务层 -->
<bean id="hourEmpServiceImpl" class="com.csdn.service.HourEmpServiceImpl" autowire="byType" >
<!—autowire的定义为byType -->
</bean>
//empServiceImpl的代码
package com.csdn.service;
public class EmpServiceImpl {
/**定义一个变量实例*/
private String name;
/**通过set方法进行赋值*/
public void setName(String name) {
this.name = name;
}
}
// hourEmpServiceImpl的代码
package com.csdn.service;
public class HourEmpServiceImpl {
/**定义一个EmpServiceImpl的操作对象*/
private EmpServiceImpl empServiceImpl;
/**生成相应的set方法 通过set方法注入的*/
public void setEmpServiceImpl(EmpServiceImpl empServiceImpl) {
this.empServiceImpl = empServiceImpl;
}
}
// HourAddressServiceImpl的代码
package com.csdn.service;
//这里只是继承了EmpServiceImpl的实例javabean
public class HourAddressServiceImpl extends EmpServiceImpl {
}
//junit测试类代码
@Test
public void test(){
ApplicationContext ac = new ClassPathXmlApplicationContext("app.xml");
HourEmpServiceImpl hsi=(HourEmpServiceImpl) ac.getBean("hourEmpServiceImpl");
}
注意:父类与子类匹配的方式是:子类自动装载成父类的对象。
接口与实现类:实现类的对象可以自动装载到接口的对象。否则会出现空指针异常。