一:依赖注入
通过第一个Spring程序之后,创建对象的工作会交给Spring来完成,只需要在配置文件上配置相关的<bean>节点,通过Spring容器就可以根据配置创建对象。
回顾上一个spring配置文件:
<bean name="UserDao" class="yzr.dao.UserDao" ></bean>
<bean name="UserService" class="yzr.service.UserService" >
<property name="userDao" ref="UserDao"></property>
</bean>
<bean name="UserAction" class="yzr.action.UserAction" >
<property name="userService" ref="UserService"></property>
</bean>
这种是通过属性方式的依赖注入,在<bean>节点内包含<property>节点,指定相应的依赖关系。在这种情况下,在Service中需要声明一个关于UserDao的set方法,就像这样:
package yzr.service;
import yzr.dao.UserDao;
public class UserService {
private UserDao userDao=null;
public void setUserDao(UserDao userdao){
userDao=userdao;
}
public void run(){
userDao.run();
System.out.println("Service执行Run");
}
}
注意的地方是,<property name="userDao" ref="UserDao"></property>中name的值为userDao,与Service类中的属性变量userDao必须一致,注意大小写。
除了上面这种通过属性依赖注入的方式,还有另外一种通过构造函数注入依赖,使用<constructor-arg>节点。
<bean name="UserDao" class="yzr.dao.UserDao" ></bean>
<!--
<bean name="UserService" class="yzr.service.UserService" >
<property name="userDao" ref="UserDao"></property>
</bean>
-->
<bean name="UserService" class="yzr.service.UserService" >
<constructor-arg ref="UserDao"></constructor-arg>
</bean>
<bean name="UserAction" class="yzr.action.UserAction" >
<property name="userService" ref="UserService"></property>
</bean>
通过构造函数注入的话,Service需要提供一个带依赖类型的构造函数,比如这样:
package yzr.service;
import yzr.dao.UserDao;
public class UserService {
private UserDao userDao=null;
/*
public void setUserDao(UserDao userdao){
userDao=userdao;
}
*/
public void run(){
userDao.run();
System.out.println("Service执行Run");
}
public UserService(){
}
public UserService(UserDao userDao){
this.userDao=userDao;
}
}
通过上面两个例子可以往被创建对象注入值(或者对象),此外,假若当需要注入的依赖为集合或者map类型时,spring也提供了相应的节点配置,下面使用属性注入方式说明:
1.注入List集合:
1)将String类型值注入集合中用value节点
<bean name="UserAction" class="yzr.action.UserAction" >
<property name="userService" ref="UserService"></property>
<property name="stringList">
<list>
<value>YZR</value>
</list>
</property>
</bean>
相应的Action中声明一个stringList属性变量:
private List stringList=null;
public void setStringList(List actionList) {
this.stringList = actionList;
}
2)将对象类型注入集合中,使用bean节点
<property name="beanList">
<list>
<bean id="Userbean" class="yzr.entity.UserBean">
<property name="name" value="YZR"></property>
</bean>
</list>
</property>
相应的Action中声明一个beanList属性变量:
private List beanList=null;
public void setBeanList(List beanList) {
this.beanList = beanList;
}
3)使用ref注入已有的bean
<bean name="UserAction" class="yzr.action.UserAction" >
<property name="beanList">
<list>
<ref bean="Userbean"/>
</list>
</property>
</bean>
<bean id="Userbean" class="yzr.entity.UserBean">
<property name="name" value="YZR"></property>
</bean>
2.注入Map键值对:
同理 与List,下面三种方式就写在一起表示:
<property name="maps">
<map>
<entry key="StringKey" value="1" />
<entry key="BeanKey" value-ref="Userbean" />
<entry key="BeanKey2">
<bean id="Userbean" class="yzr.entity.UserBean">
<property name="name" value="YZR"></property>
</bean>
</entry>
</map>
</property>
3.注入prop属性文件的键值对:
propertise属性文件的内容只能是文本类型的键值对,所以在prop节点内写上文本即可。
<property name="pros">
<props>
<prop key="StringKey">StringValue</prop>
</props>
</property>
二 P命名空间
spring IOC容器在创建对象的时候,很多场景需要注入依赖,在使用属性方式注入时,编写property节点会很常用,为了简化配置文件关于property的写法,spring提供了P名称空间:
xmlns:p="http://www.springframework.org/schema/p"
在编写bean节点的时候,可以使用
p:属性变量=值
<!--String类型注入-->
<bean id="user" class="yzr.entity.UserBean" p:name="StringValue"></bean>
<!--Bean对象注入-->
<bean id="user" class="yzr.entity.UserBean" p:myBean-ref="BeanId"></bean>
三 spring注解
使用注解的方式来简化使用配置文件方式创建对象的过程:
@Repository 在持久层使用 (dao)
@Service 在业务逻辑层使用 (service)
@Controller 在控制层使用 (action)
@Component 把对象加入IOC容器,都可以使用这个注解 (通用)
@Resource 注入属性值: 从容器中找指定名称的对象,如果没有指定名称,用修饰的成员变量名称!
Dao:
package yzr.dao;
import org.springframework.stereotype.Repository;
@Repository
public class UserDao {
public void run(){
System.out.println("UserDao执行Run;");
}
}
Service:
package yzr.service;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import yzr.dao.UserDao;
@Service
public class UserService {
@Resource
private UserDao userDao=null;
/*
public void setUserDao(UserDao userdao){
userDao=userdao;
}
*/
public void run(){
userDao.run();
System.out.println("Service执行Run");
}
public UserService(){
}
}
Action:
package yzr.action;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Controller;
import yzr.service.UserService;
@Controller
public class UserAction {
@Resource
private UserService userService=null;
public String execute() throws Exception{
userService.run();
System.out.println("UserAction执行execute");
//System.out.println(stringList);
//System.out.println(beanList);
return "success";
}
}
applicationContext.xml配置文件:
<?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:p="http://www.springframework.org/schema/p"
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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="yzr"></context:component-scan>
</beans>
测试:
package yzr.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.Resource;
import yzr.action.UserAction;
public class app {
String path="ApplicationContext.xml";
@Test
public void test() throws Exception{
ClassPathXmlApplicationContext ac=new ClassPathXmlApplicationContext(path);
System.out.println("加载配置文件完成");
//UserAction action=(UserAction) ac.getBean("UserAction");
//action.execute();
UserAction action =null;
action=ac.getBean(UserAction.class);
action.execute();
}
}
比如:在已经使用了注解的方式的前提下,然后又在配置文件中加上对UserAction的bean:
<?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:p="http://www.springframework.org/schema/p"
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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="yzr"></context:component-scan>
<bean name="UserAction" class="yzr.action.UserAction" ></bean>
</beans>
package yzr.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.Resource;
import yzr.action.UserAction;
public class app {
String path="ApplicationContext.xml";
@Test
public void test() throws Exception{
ClassPathXmlApplicationContext ac=new ClassPathXmlApplicationContext(path);
System.out.println("加载配置文件完成");
//UserAction action=(UserAction) ac.getBean("UserAction");
//action.execute();
UserAction action =null;
action=ac.getBean(UserAction.class);
action.execute();
}
}
当getBean(UserAction.class)时会报错,报错信息为:
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [yzr.action.UserAction] is defined: expected single matching bean but found 2: userAction,UserAction
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:289)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1125)
at yzr.test.app.test(app.java:21)
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.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
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: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)
因为使用注解的方式spring会自动创建一个UserAction对象,而在此时我们又手动在配置文件下又加上了一个UserAction类型的bean,所以使用getBean(UserAction.class)时spring容器创建对象时会找到两个UserAction。需要去掉其中一个才对。
所以,xml配置模式和注解在不冲突的条件下可以一起使用,但如果存在重复的时候spring会报错。