spring的两种注入方式:xml形式及注解形式,xml形式在上一篇文章差不多已讲解,在这主要叙述一下spring的注解形式。
在用注解之前需要
a.加入common-annotations.jar包,还有spring.jar最好用2.5以上的,说是说spring.jar 2.0支持,可我在测试的过程发现用spring.jar 2.0好象有问题,后来换成2.5后就好使了。
b.需加入它的命名空间
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
代码如下:
applicationContext.xml
PersonDao.java
PersonDaoImp.java
PersonService.java
PersonServiceImp.java
Test.java
说明:按PersonServiceImp.java里的四种形式写都是可以实现注解的,因为注解可以按名称及类型进行,默认按名称,在名称不存在时就按类型进行注解,其中括号里的注解名称可有可无,其原理可以看下面代码:
在用注解之前需要
a.加入common-annotations.jar包,还有spring.jar最好用2.5以上的,说是说spring.jar 2.0支持,可我在测试的过程发现用spring.jar 2.0好象有问题,后来换成2.5后就好使了。
b.需加入它的命名空间
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
代码如下:
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: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">
<!--要使用注解的话,必须打开该配置项。通过这个配置项,就可以打开针对注解的处理器把它注入到Spring容器中-->
<context:annotation-config/>
<bean id="personDao" class="com.luojing.test.daoimp.PersonDaoImp"/>
<bean id="service" class="com.luojing.test.serviceimp.PersonServiceImp">
</bean>
</beans>
PersonDao.java
package com.luojing.test.dao;
public interface PersonDao {
public void add();
}
PersonDaoImp.java
package com.luojing.test.daoimp;
import org.springframework.stereotype.Repository;
import com.luojing.test.dao.PersonDao;
@Repository
public class PersonDaoImp implements PersonDao {
public void add() {
System.out.println("执行了add()方法!!!");
}
}
PersonService.java
package com.luojing.test.service;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public interface PersonService {
public void save();
}
PersonServiceImp.java
package com.luojing.test.serviceimp;
import javax.annotation.Resource;
import com.luojing.test.dao.PersonDao;
import com.luojing.test.service.PersonService;
public class PersonServiceImp implements PersonService {
//第一种形式
@Resource(name="personDao")
private PersonDao personDao;
//第二种形式
//private PersonDao personDao;
//@Resource
//public void setPersonDao(PersonDao personDao) {
// this.personDao = personDao;
//}
//第三种形式
//private PersonDao personDao;
//@Resource(name="personDao")
//public void setPersonDao(PersonDao personDao) {
// this.personDao = personDao;
//}
//第四种形式
//@Resource
//private PersonDao personDao;
public void save() {
personDao.add();
}
}
Test.java
package com.luojing.test.testioc;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.luojing.test.service.PersonService;
public class Test {
public static void main(String args[]){
AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
PersonService ps1 = (PersonService)ctx.getBean("service");
ps1.save();
System.out.println(ps1);
ctx.close();
}
}
说明:按PersonServiceImp.java里的四种形式写都是可以实现注解的,因为注解可以按名称及类型进行,默认按名称,在名称不存在时就按类型进行注解,其中括号里的注解名称可有可无,其原理可以看下面代码:
/**
* 利用注解为bean的属性注入值
*/
private void annotationInject() {
for(String beanName : sigletons.keySet()){//循环所有的bean对象
Object bean = sigletons.get(beanName);
if(bean!=null){//获取到bean对象后就判断下bean对象是否存在
try {
//对属性进行处理
PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
//获取bean的属性
for(PropertyDescriptor properdesc : ps){//for循环属性描述
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){//当找不到与名称匹配的bean会按类型去寻找
for(String key : sigletons.keySet()){//for循环所有的bean对象
if(properdesc.getPropertyType().isAssignableFrom(sigletons.get(key).getClass())){
//判断属性的类型是否和bean想匹配
//isAssignableFrom这个方法判断properdesc.getPropertyType()这个类型是否是
//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())){ //检查被注解的字段是否存在注解名称,存在按名称查找给bean注入属性值,不存在按默认字段名查找给bean注入属性值
value = sigletons.get(resource.name());
}else{
value = sigletons.get(field.getName());
if(value==null){
for(String key : sigletons.keySet()){ //如果都没找到我们再根据属性的类型去Spring容器寻找跟这个类型匹配的bean,然后再把它给注入进来
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();
}
}
}
}