您的位置:首页 > 编程语言 > Java开发

Spring注入依赖对象

2016-01-03 23:28 471 查看
1,依赖注入

使用属性setter方法注入

使用构造器注入

使用Field注入(用于注解方式)

2,setter方法注入

Bean对象注入:

方式一

<bean id="orderDao"class="cn.itcast.service.OrderDaoBean"/>

<bean id="orderService"class="cn.itcast.service.OrderServiceBean">

<propertyname="orderDao"ref="orderDao"/>

</bean>

方式二(使用内部bean,但该bean不能被其他bean使用)

<bean id="orderService"class="cn.itcast.service.OrderServiceBean">

<propertyname="orderDao">

<bean class="cn.itcast.service.OrderDaoBean"/>

</property>

</bean>

基本类型对象注入:

<bean id="orderService"class="cn.itcast.service.OrderServiceBean">

<propertyname=“name” value=“zhao/>//属性setter方法注入

</bean>

集合类型注入:

<beanid="order" class="cn.itcast.service.OrderServiceBean">

<property name="lists">

<list>

<value>lihuoming</value>

</list>

</property>

<property name="sets">

<set>

<value>set</value>

</set>

</property>

<property name="maps">

<map>

<entry key="lihuoming"value="28"/>

</map>

</property>

<property name="properties">

<props>

<prop key="12">sss</prop>

</props>

</property>

</bean>

setter方法Spring内部注入原理:

<span style="font-size:18px;">package cn.itcast.dao;

import java.beans.*;
import java.util.*;
import java.lang.reflect.Method;
import java.net.URL;
import org.apache.commons.beanutils.ConvertUtils;
import org.dom4j.io.SAXReader;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.XPath;

interface PersonDao {
public void add();
}
class PersonDaoBean implements PersonDao {
public void add(){
System.out.println("执行PersonDaoBean中的add()方法");
}
}
interface PersonService {
public void save();
}
class PersonServiceBean implements PersonService {
private PersonDao personDao;
public PersonDao getPersonDao() {
return personDao;
}
public void setPersonDao(PersonDao personDao) {
this.personDao = personDao;
}
public void save(){
personDao.add();
}
}
class BeanDefinition {
private String id;
private String className;
private List<PropertyDefinition> propertys = new ArrayList<PropertyDefinition>();

public BeanDefinition(String id, String className) {
this.id = id;
this.className = className;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public List<PropertyDefinition> getPropertys() {
return propertys;
}
public void setPropertys(List<PropertyDefinition> propertys) {
this.propertys = propertys;
}
}
class MyClassPathXMLApplicationContext {
private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();
private Map<String, Object> sigletons = new HashMap<String, Object>();

public MyClassPathXMLApplicationContext(String filename){
this.readXML(filename);
this.instanceBeans();
this.injectObject();
}
/**
* 为bean对象的属性注入值
*/
private void injectObject() {
for(BeanDefinition beanDefinition : beanDefines){
Object bean = sigletons.get(beanDefinition.getId());
if(bean!=null){
try {
PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
for(PropertyDefinition propertyDefinition : beanDefinition.getPropertys()){
for(PropertyDescriptor properdesc : ps){
if(propertyDefinition.getName().equals(properdesc.getName())){
Method setter = properdesc.getWriteMethod();//获取属性的setter方法 ,private
if(setter!=null){
Object value = null;
if(propertyDefinition.getRef()!=null && !"".equals(propertyDefinition.getRef().trim())){
value = sigletons.get(propertyDefinition.getRef());
}else{
value = ConvertUtils.convert(propertyDefinition.getValue(), properdesc.getPropertyType());
}
setter.setAccessible(true);
setter.invoke(bean, value);//把引用对象注入到属性
}
break;
}
}
}
} catch (Exception e) {
}
}
}
}
/**
* 完成bean的实例化
*/
private void instanceBeans() {
for(BeanDefinition beanDefinition : beanDefines){
try {
if(beanDefinition.getClassName()!=null && !"".equals(beanDefinition.getClassName().trim()))
sigletons.put(beanDefinition.getId(), Class.forName(beanDefinition.getClassName()).newInstance());
<span style="white-space:pre">	</span>} catch (Exception e) {
e.printStackTrace();
}
}

}
/**
* 读取xml配置文件
* @param filename
*/
@SuppressWarnings("unchecked")
private void readXML(String filename) {
SAXReader saxReader = new SAXReader();
Document document=null;
try{
URL xmlpath = this.getClass().getClassLoader().getResource(filename);
document = saxReader.read(xmlpath);
Map<String,String> nsMap = new HashMap<String,String>();
nsMap.put("ns","http://www.springframework.org/schema/beans");//加入命名空间
XPath xsub = document.createXPath("//ns:beans/ns:bean");//创建beans/bean查询路径
xsub.setNamespaceURIs(nsMap);//设置命名空间
List<Element> beans = xsub.selectNodes(document);//获取文档下所有bean节点
for(Element element: beans){
String id = element.attributeValue("id");//获取id属性值
String clazz = element.attributeValue("class"); //获取class属性值
BeanDefinition beanDefine = new BeanDefinition(id, clazz);
XPath propertysub =  element.createXPath("ns:property");
propertysub.setNamespaceURIs(nsMap);//设置命名空间
List<Element> propertys = propertysub.selectNodes(element);
for(Element property : propertys){
String propertyName = property.attributeValue("name");
String propertyref = property.attributeValue("ref");
String propertyValue = property.attributeValue("value");
PropertyDefinition propertyDefinition = new PropertyDefinition(propertyName, propertyref, propertyValue);
beanDefine.getPropertys().add(propertyDefinition);
}
beanDefines.add(beanDefine);
}
}catch(Exception e){
e.printStackTrace();
}
}
/**
* 获取bean实例
* @param beanName
* @return
*/
public Object getBean(String beanName){
return this.sigletons.get(beanName);
}
}
class PropertyDefinition {
private String name;
private String ref;
private String value;

public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public PropertyDefinition(String name, String ref, String value) {
this.name = name;
this.ref = ref;
this.value = value;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRef() {
return ref;
}
public void setRef(String ref) {
this.ref = ref;
}
}
public class SpringTest {
public static void main(String[]args){
MyClassPathXMLApplicationContext ctx = new MyClassPathXMLApplicationContext("beans.xml");
PersonService personService = (PersonService)ctx.getBean("personService");
personService.save();
//ctx.close();
}
}
beans.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
           <bean id="personDao" class="cn.itcast.dao.impl.PersonDaoBean"></bean>
          <bean id="personService" class="cn.itcast.service.impl.PersonServiceBean">
          <span style="white-space:pre">	</span><!--  使用内部bean进行注入
          <span style="white-space:pre">	</span><property name="personDao">
          <span style="white-space:pre">		</span><bean class="cn.itcast.dao.impl.PersonDaoBean"/>
          <span style="white-space:pre">	</span></property>
          <span style="white-space:pre">	</span> -->
          <span style="white-space:pre">	</span><property name="personDao" ref="personDao"/>
          <span style="white-space:pre">	</span><property name="name" value="itcast"/>
          <span style="white-space:pre">	</span><property name="id" value="88"/>
          </bean>
</beans>


3,构造器注入

<bean id="personDao" class="cn.com.impl.PersonServiceBean"></bean>

<bean id="orderService" class="cn.itcast.service.OrderServiceBean">

<constructor-arg index=“0” type=“java.lang.String” value=“xxx”/>//构造器注入

<constructor-arg index=“1” value=“效果和0是一样的,不用写type”/>//构造器注入

<constructor-arg index=“2” type=“cn.com.dao.PersonDao” ref="personDao"/>//构造器注入

</bean>

4,使用Field注入(用于注解方式)

在java代码中使用@Autowired或@Resource注解方式进行装配。但我们需要在xml配置文件中配置以下信息:

<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"

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">
<context:annotation-config/>

</beans>

这个配置隐式注册了多个对注释进行解析处理的处理器:AutowiredAnnotationBeanPostProcessor,CommonAnnotationBeanPostProcessor,PersistenceAnnotationBeanPostProcessor,RequiredAnnotationBeanPostProcessor

注:@Resource注解在spring安装目录的lib\j2ee\common-annotations.jar

在java代码中使用@Autowired或@Resource注解方式进行注入,这两个注解的区别是:@Autowired 默认按类型装配,@Resource默认按名称装配,当找不到与名称匹配的bean才会按类型装配。

@Autowired

private PersonDao personDao;//用于字段上

@Autowired

public void setOrderDao(OrderDao orderDao) {//用于属性的setter方法上

this.orderDao = orderDao;

}

@Autowired注解是按类型装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它required属性为false,如果设置为true,则说明必须要注入值,否则会抛异常。如果我们想使用按名称装配,可以结合@Qualifier注解一起使用。如下:这个是spring框架的。

@Autowired @Qualifier("personDaoBean")

private PersonDao personDao;

@Resource注解和@Autowired一样,也可以标注在字段或属性的setter方法上,但它默认按名称装配。名称可以通过@Resource的name属性指定,如果没有指定name属性,当注解标注在字段上,即默认取字段的名称作为bean名称寻找依赖对象,当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找依赖对象。这个注解是jdk提供支持的,建议用这个,避免与spring框架产生耦合。

@Resource(name=“personDaoBean”)

private PersonDao personDao;//用于字段上

注意:如果没有指定name属性,并且按照默认的名称仍然找不到依赖对象时,@Resource注解会回退到按类型装配。但一旦指定了name属性,就只能按名称装配了。

注解方法Spring内部注入原理:

package junit.test;

import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.*;
import org.apache.commons.beanutils.ConvertUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;

interface PersonDao {
public void add();
}
class PersonDaoBean implements PersonDao {
public void add(){
System.out.println("执行PersonDaoBean中的add()方法");
}
}
interface PersonService {
public void save();
}
class PersonServiceBean implements PersonService {
@ItcastResource private PersonDao personDao;
private String name;
public void setPersonDao(PersonDao personDao) {
this.personDao = personDao;
}
public PersonServiceBean(){}
public PersonServiceBean(PersonDao personDao, String name) {
this.personDao = personDao;
this.name = name;
}
public void save(){
//System.out.println(name);
personDao.add();
}
}
class BeanDefinition {
private String id;
private String className;
private List<PropertyDefinition> propertys = new ArrayList<PropertyDefinition>();

public BeanDefinition(String id, String className) {
this.id = id;
this.className = className;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public List<PropertyDefinition> getPropertys() {
return propertys;
}
public void setPropertys(List<PropertyDefinition> propertys) {
this.propertys = propertys;
}
}
class MyClassPathXMLApplicationContext {
private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();
private Map<String, Object> sigletons = new HashMap<String, Object>();

public MyClassPathXMLApplicationContext(String filename){
this.readXML(filename);
this.instanceBeans();
this.annotationInject();
this.injectObject();
}
/**
* 通过注解实现注入依赖对象
*/
private void annotationInject() {
for(String beanName : sigletons.keySet()){
Object bean = sigletons.get(beanName);
if(bean!=null){
try {
PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
for(PropertyDescriptor properdesc : ps){
Method setter = properdesc.getWriteMethod();//获取属性的setter方法
if(setter!=null && setter.isAnnotationPresent(ItcastResource.class)){
ItcastResource resource = setter.getAnnotation(ItcastResource.class);
Object value = null;
if(resource.name()!=null && !"".equals(resource.name())){
value = sigletons.get(resource.name());
}else{
value = sigletons.get(properdesc.getName());
if(value==null){
for(String key : sigletons.keySet()){
if(properdesc.getPropertyType().isAssignableFrom(sigletons.get(key).getClass())){
value = sigletons.get(key);
break;
}
}
}
}
setter.setAccessible(true);
setter.invoke(bean, value);//把引用对象注入到属性
}
}
Field[] fields = bean.getClass().getDeclaredFields();
for(Field field : fields){
if(field.isAnnotationPresent(ItcastResource.class)){
ItcastResource resource = field.getAnnotation(ItcastResource.class);
Object value = null;
if(resource.name()!=null && !"".equals(resource.name())){
value = sigletons.get(resource.name());
}else{
value = sigletons.get(field.getName());
if(value==null){
for(String key : sigletons.keySet()){
if(field.getType().isAssignableFrom(sigletons.get(key).getClass())){
value = sigletons.get(key);
break;
}
}
}
}
field.setAccessible(true);//允许访问private字段
field.set(bean, value);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

/**
* 为bean对象的属性注入值
*/
private void injectObject() {
for(BeanDefinition beanDefinition : beanDefines){
Object bean = sigletons.get(beanDefinition.getId());
if(bean!=null){
try {
PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
for(PropertyDefinition propertyDefinition : beanDefinition.getPropertys()){
for(PropertyDescriptor properdesc : ps){
if(propertyDefinition.getName().equals(properdesc.getName())){
Method setter = properdesc.getWriteMethod();//获取属性的setter方法 ,private
if(setter!=null){
Object value = null;
if(propertyDefinition.getRef()!=null && !"".equals(propertyDefinition.getRef().trim())){
value = sigletons.get(propertyDefinition.getRef());
}else{
value = ConvertUtils.convert(propertyDefinition.getValue(), properdesc.getPropertyType());
}
setter.setAccessible(true);
setter.invoke(bean, value);//把引用对象注入到属性
}
break;
}
}
}
} catch (Exception e) {
}
}
}
}
/**
* 完成bean的实例化
*/
private void instanceBeans() {
for(BeanDefinition beanDefinition : beanDefines){
try {
if(beanDefinition.getClassName()!=null && !"".equals(beanDefinition.getClassName().trim()))
sigletons.put(beanDefinition.getId(), Class.forName(beanDefinition.getClassName()).newInstance());
} catch (Exception e) {
e.printStackTrace();
}
}

}
/**
* 读取xml配置文件
* @param filename
*/
private void readXML(String filename) {
SAXReader saxReader = new SAXReader();
Document document=null;
try{
URL xmlpath = this.getClass().getClassLoader().getResource(filename);
document = saxReader.read(xmlpath);
Map<String,String> nsMap = new HashMap<String,String>();
nsMap.put("ns","http://www.springframework.org/schema/beans");//加入命名空间
XPath xsub = document.createXPath("//ns:beans/ns:bean");//创建beans/bean查询路径
xsub.setNamespaceURIs(nsMap);//设置命名空间
List<Element> beans = xsub.selectNodes(document);//获取文档下所有bean节点
for(Element element: beans){
String id = element.attributeValue("id");//获取id属性值
String clazz = element.attributeValue("class"); //获取class属性值
BeanDefinition beanDefine = new BeanDefinition(id, clazz);
XPath propertysub =  element.createXPath("ns:property");
propertysub.setNamespaceURIs(nsMap);//设置命名空间
List<Element> propertys = propertysub.selectNodes(element);
for(Element property : propertys){
String propertyName = property.attributeValue("name");
String propertyref = property.attributeValue("ref");
String propertyValue = property.attributeValue("value");
PropertyDefinition propertyDefinition = new PropertyDefinition(propertyName, propertyref, propertyValue);
beanDefine.getPropertys().add(propertyDefinition);
}
beanDefines.add(beanDefine);
}
}catch(Exception e){
e.printStackTrace();
}
}
/**
* 获取bean实例
* @param beanName
* @return
*/
public Object getBean(String beanName){
return this.sigletons.get(beanName);
}
}
@Retention(RetentionPolicy.RUNTIME)//注解是保留在运行期,编译后的class,还是源文件。
@Target({ElementType.FIELD, ElementType.METHOD})
//注解可以标注在什么地方。这里可以标注在字段/方法上,也可以在类上,参数类型是数组
@interface ItcastResource {
public String name() default "";//模拟@Resoure注解。它里面有个name属性
}
class PropertyDefinition {
private String name;
private String ref;
private String value;

public String getValue() {
return value;
}

public void setValue(String value) {
this.value = value;
}
public PropertyDefinition(String name, String ref, String value) {
this.name = name;
this.ref = ref;
this.value = value;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRef() {
return ref;
}
public void setRef(String ref) {
this.ref = ref;
}
}
public class SpringTest {
public static void main(String[]args){
MyClassPathXMLApplicationContext ctx = new MyClassPathXMLApplicationContext("beans.xml");
PersonService personService = (PersonService)ctx.getBean("personService");
personService.save();
//ctx.close();
}
}
<?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"
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"> 
<context:annotation-config/>

<bean id="personDaoxxxx" class="cn.itcast.dao.impl.PersonDaoBean"></bean>
<bean id="personService" class="cn.itcast.service.impl.PersonServiceBean">
<!--
<constructor-arg index="0" type="cn.itcast.dao.PersonDao" ref="personDao"/>
<constructor-arg index="1" value="传智播客"/>
-->
</bean>
</beans>
5,自动注入

上面讲的都是手动注入,对于自动注入了解一下就可以了,实在不推荐使用。例子:

<beanid="..." class="..."
autowire="byType"/>
autowire属性取值如下:
byType:按类型装配,可以根据属性的类型,在容器中寻找跟该类型匹配的bean。如果发现多个,那么将会抛出异常。如果没有找到,即属性值为null。
byName:按名称装配,可以根据属性的名称,在容器中寻找跟该属性名相同的bean,如果没有找到,即属性值为null。
constructor与byType的方式类似,不同之处在于它应用于构造器参数。如果在容器中没有找到与构造器参数类型一致的bean,那么将会抛出异常。
autodetect:通过bean类的自省机制(introspection)来决定是使用constructor还是byType方式进行自动装配。如果发现默认的构造器,那么将使用byType方式。
6,通过在classpath自动扫描方式把组件纳入spring容器中管理

前面的例子我们都是使用XML的bean定义来配置组件。在一个稍大的项目中,通常会有上百个组件,如果这些这组件采用xml的bean定义来配置,显然会增加配置文件的体积,查找及维护起来也不太方便。spring2.5为我们引入了组件自动扫描机制,spring2.0是没有的,他可以在类路径底下寻找标注了@Component、@Service、@Controller、@Repository注解的类,并把这些类纳入进spring容器中管理。它的作用和在xml文件中使用bean节点配置组件是一样的。要使用自动扫描机制,我们需要打开以下配置信息:

<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"

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">
<context:component-scan base-package="cn.itcast"/>

</beans>

其中base-package为需要扫描的包(含子包)。

@Service用于标注业务层组件、@Controller用于标注控制层组件(如struts中的action)、@Repository用于标注数据访问组件,即DAO组件。而@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。

@Service("personService")//如果不写,默认是personServiceBean,这样写的话,默认是单例模式的。<pre name="code" class="java">//<span style="font-family: Arial, Helvetica, sans-serif;">如果想变成原型,需要加</span>@Scope("prototype")
public class PersonServiceBean implements PersonService {//@Autowired(required=false) @Qualifier("personDaoxxxx")private PersonDao personDao;@PostConstruct//相当于调用该bean时执行的初始化方法public void init(){System.out.println("初始化");}@PreDestroy//相当于销毁该bean前执行的方法public
void destory(){System.out.println("开闭资源");}public void setPersonDao(PersonDao personDao) {this.personDao = personDao;}public void save(){personDao.add();}}

public static void main(String[]args){
<span style="white-space:pre">		</span>AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
<span style="white-space:pre">		</span>PersonService personService = (PersonService)ctx.getBean("personService");
<span style="white-space:pre">		</span>ctx.close();
<span style="white-space:pre">	</span>}
<?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"       
       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">          
          <context:component-scan base-package="cn.com"/>cn.com包下的所有类只有标注就都会纳入Spring容器进行管理
</beans>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: