- 浏览: 386661 次
- 性别:
- 来自: 印度
文章分类
最新评论
-
天天来注册:
...
多线程的死锁 -
memoryisking:
可以看看这篇文章,这个是struts教程网上一个简单的例子,构 ...
Java5中的线程池实例讲解 -
a123159521:
菜鸟不再菜 写道楼主很明显没有说明守护线程到底是怎么服务Use ...
守护线程总结 -
jjruanlili:
要搞个executor和nio的结合,差不多
Java5中的线程池实例讲解 -
josico:
纠正楼主一个问题‘如果四个队员都在忙时,再有新的任务,这个小组 ...
线程池ThreadPoolExecutor使用简介
一、定义:Spring 是一个开源的控制反转(Inversion of Control,IoC/DI)和面向切面(AOP)的容器框架,它的主要目的是简化企业开发
二、实例化Spring容器:
方法一:在类路径下寻找配置文件来实例化容器
ApplicationContext ctx =
new ClassPathXmlApplicationContext(new String[]{“beans.xml”});
方法二:在文件系统路径下寻找配置文件来实例化容器
ApplicationContext ctx =
new FileSystemXmlApplicationContext(new String[]{“d:""beans.xml”});
注:文件可指定多个
可建立单元测试来测试Spring容器的初始化
三、编写Spring 配置文件时,不能出现帮助信息的解决办法—添加schema文件
由于Spring的schema文件位于网络上,如果机器不能连接到网络,那么在写配置文件的时候就无法出现提示信息,解决办法有两种:
1. 让机器上网,Eclipse会自动从网络上下载schema文件并缓存在硬盘上
2.手动添加schema文件,方法如下:
windows->preferences->myeclipse->files and editors->xml->xmlcatalog
a. 我们可以选择将schema文件放到User Specified Entries然后点击‘add’,在出现的窗口中的Key Type中选择URL, 在‘Location’中选择‘File System’,然后在Spring解压目录的dist/resources目录中选择spring-beans-2.5.xsd,
b. 回到设置窗口时候不要急于关闭窗口,应把窗口中的Key Type改为schema location,
c. key改为:
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
四、Spring 配置文件一个小插曲
<bean id=”” name=””></bean>,在这里,id 和name都是为这个bean取的名字,其实这两者意思相同,只是如果选择使用的是id,那么id命名则不能有特殊字符,如果使用的是name则可以使用特殊字符作为name。如
<bean id=”beanId” /> && <bean name=”bean-name”/>
五、Spring容器如何管理bean
首先读取beans.xml里的bean配置所有的id、class的值,作为String形式保存至对应一个Bean,形成bean列表
利用反射机制,将bean列表遍历,生成对象,如下:
package junit.test;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;
/**
*传智传客版容器
*
*/
publicclass ItcastClassPathXMLApplicationContext {
private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();
private Map<String, Object> sigletons = new HashMap<String, Object>();
public ItcastClassPathXMLApplicationContext(String filename){
this.readXML(filename);
this.instanceBeans();
}
/**
*完成bean的实例化
*/
privatevoid 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配置文件
*@paramfilename
*/
privatevoid 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);
beanDefines.add(beanDefine);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
*获取bean实例
*@parambeanName
*@return
*/
public Object getBean(String beanName){
returnthis.sigletons.get(beanName);
}
}
六、Spring的三种实例化Bean方式
1.使用构造器实例化
<bean id="personService" class="cn.itcast.service.impl.PersonServiceBean"></bean>
这种就是利用默认的构造器进行的实例化
2. 静态工厂方法实例化
<bean id="personService2" class="cn.itcast.service.impl.PersonServiceBeanFactory" factory-method="createPersonServiceBean"/>
3. 使用实例工厂方法实例化
<bean id="personServiceFactory" class="cn.itcast.service.impl.PersonServiceBeanFactory"/>
<bean id="personService3" factory-bean="personServiceFactory" factory-method="createPersonServiceBean2"/>
七、bean的作用域-属性scope
singleton:(默认)在每个Spring IOC容器中一个bean定义只有一个对象实例,默认情况下会在容器启动时初始化bean。但我们可以指定bean节点lazy-init=”true” 则表示不需要在容器初始化时候对bean进行初始化,只有在第一次getBean时候进行初始化,如果需要所有的bean都应用延迟初始化,可以在根节点<beans>设置default-lazy-init=”true”(不推荐,不利于观察bean初始化情况)
prototype:每次从容器中获取的bean都是新的对象
request
session
global session
七、Spring管理的bean的生命周期
默认情况下容器初始化的时候对bean进行实例化
如果scope为prototype时,在调用getBean方法时候对bean进行实例化
如果lazy-init为true时,容器初始化时候不会对bean进行实例化
综上所述,Spring管理的bean初始化点根据设定的条件不同而不同
init-method:在bean被实例化的后即会执行的方法
destroy-method:在bean被销毁的时候执行的方法(如果没有手动的销毁该bean,则只有在容器关闭的时候才会销毁)
正常的关闭Spring容器
AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
ctx.close();
八、控制反转IoC 定义:
Public class PersonServiceBean {
Private PersonDao personDao = new PersonDaoBean();
Public void save (Person person) {
personDao.save(person);
}
}
PersonDaoBean是在应用内部创建和维护的,所谓的控制反转就是应用本身不负责依赖对象的创建和维护,依赖对象的创建及维护是由外部容器负责的,这样控制权就由应用转移到了外部容器,控制权的转移就是所谓的反转。
九、依赖注入(Dependency Injection)的定义:
当我们把依赖对象交给外部容器负责创建,那么PersonServiceBean类可以改成如下:
public class PersonServiceBean{
private PersonDao personDao;
//通过构造器参数,让容器把创建好的依赖对象注入进PersonServiceBean,当然也可以使用setter方法进行注入
public PersonServiceBean(PersonDao personDao) {
this.personDao = personDao;
}
Public void save(Person person) {
personDao.save(person);
}
}
所谓的依赖注入就是指:在运行期,由外部容器动态地将依赖对象注入到组件中
十、依赖注入:
1.使用构造器注入
private PersonDao personDao;
private String name;
public PersonServiceBean(PersonDao personDao, String name) {
this.personDao = personDao;
this.name = name;
}
beans.xml配置:
<bean id="personService" class="cn.itcast.service.impl.PersonServiceBean">
<constructor-arg index="0" type="cn.itcast.dao.PersonDao" ref=""></constructor-arg>
<constructor-arg index="1" type="paramValue"></constructor-arg>
</bean>
2.使用setter方法注入
ref形式注入:
<bean id="personService" class="cn.itcast.service.impl.PersonServiceBean">
<property name="personDao" ref="personDaoBean" />
</bean>
可以采用内部bean方式进行注入,不同过ref方式的是,这种内部bean注入对于bean的重用性效果不好:
<bean id="personService" class="cn.itcast.service.impl.PersonServiceBean">
<property name="personDao">
<bean class="cn.itcast.dao.impl.PersonDaoBean" />
</property>
</bean>
bean基本类型的注入:
<bean id="personService" class="cn.itcast.service.impl.PersonServiceBean">
<property name="personDao">
<bean class="cn.itcast.dao.impl.PersonDaoBean" />
</property>
<property name="name" value="itcast" />
<property name="id" value="100" />
</bean>
集合类的注入:
<bean id="personService" class="cn.itcast.service.impl.PersonServiceBean" >
<property name="sets">
<set>
<value>第一个</value>
<value>第二个</value>
<value>第三个</value>
</set>
</property>
<property name="lists">
<list>
<value>第一个list元素</value>
<value>第二个list元素</value>
<value>第三个list元素</value>
</list>
</property>
<property name="properties">
<props>
<prop key="key1">value1</prop>
<prop key="key2">value2</prop>
<prop key="key3">value3</prop>
</props>
</property>
<property name="maps">
<map>
<entry key="key-1" value="value-1" />
<entry key="key-2" value="value-2" />
<entry key="key-3" value="value-3" />
</map>
</property>
</bean>
3.使用Field注入(用于注解方式)
注入依赖对象,可以采用手工装配或者自动装配,在实际应用中建议使用手工装配,因为自动装配会产生未知情况,开发人员无法预见最终装配的结果
1. 手工装配依赖对象
a) 在xml配置文件中,通过在bean节点下配置
b) 在java代码中使用@Autowired或@Resource注解方式进行装配。但我们需要在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">
<!-- 相当于启用解析注解的处理器 -->
<context:annotation-config/>
</beans>
这个配置隐式注册了多个注释进行解析处理的处理器:
注解本身不做任何事情,只是利用这些处理器来达到配置一样的效果
AutowiredAnnotationBeanPostProcessor,
CommonAnnotationBeanPostProcesor,
PersistenceAnnotationBeanPostProcessor,
RquiredAnnotationBeanPostProcessor
注:@Resource注解在spring安装目录的lib/j2ee/common-annotations.jar
jar文件:
dist/spring.jar
lib/Jakarta-commons/commons-logging.jar
lib/aspectjaspectjweaver.jar、aspectjrt.jar//aop
lib/cglib/cglib-nodep-2.1_3.jar
lib/j2ee/common-annotations.jar
在java代码中使用@Autowired或@Resource注解方式进行装配,这两个注解的区别是:
@Autowired默认按类型装配,@Resource默认按照名称装配,当找不到与名称匹配的bean才会匹配的bean才会按类型装配
@Autowired
private PersonDao personDao; //用于字段上
@Autowired
public void setOrderDao(OrderDao orderDao) { //用于属性的setter方法上
this.orderDao = orderDao;
}
@Autowired注解是按类型装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它required属性为false(默认是true),如果我们想按名称装配,可以结合@Qualifier注解一起使用,如下:
@Autowired @Qualifier(“personDaoBean”)
private PersonDao personDao;
如上面的注解,则@Autowired本身是按照类型装配,现在将会按名称装配
@Resource注解和@Actowired一样,也可以标注在字段或者属性的setter方法上,但他默认按照名称装配。名称可以通过@Resource的name属性指定,如果没有指定name属性,当注解标注在字段上,即默认取字段的名称作为bean名称寻找依赖对象,当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找依赖对象。
@Resource(name=”personDaoBean”)
private PersonDao personDao;
注意:如果没有指定name属性,并且暗号默认的名称仍然找不到依赖对象时,“Resource注解会回退到按类型装配,但一旦指定了name属性,就只能按名称装配了
2.自动装配依赖对象
对于自动装配,作为了解
byType:按类型装配,可以根据属性的类型,在容器中寻找跟该类型匹配的bean。如果发现多个,那么将会抛出异常。如果没有找到,即属性值为null。
byName:按名称装配,可以根据属性的名称在容器中寻找跟该属性名相同的bean,如果没有找到,即属性值为null
constructor与byType的方式类似,不同之处在于它应用于构造器参数。如果在容器中没有找到与构造器参数类型一致的bean,那么将会抛出异常
autodetect:通过bean类的自省机制(introspection)来决定是使用constructor还是byType方式进行自动装配。如果发现默认的构造器,那么将使用byType方式
十一、依赖注入的原理
在Spring容器管理bean原理的实例中进行改造,该例子涉及到两个实体类:BeanDefinition{id,class}、PropertyDefinition{name,ref}
package junit.test;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;
/**
*传智传客版容器
*
*/
publicclass ItcastClassPathXMLApplicationContext {
private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();
private Map<String, Object> sigletons = new HashMap<String, Object>();
public ItcastClassPathXMLApplicationContext(String filename){
this.readXML(filename);
this.instanceBeans();
this.injectObject();
}
/**
*为bean对象的属性注入值
*/
privatevoid 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 = sigletons.get(propertyDefinition.getRef());
setter.setAccessible(true);
setter.invoke(bean, value);//把引用对象注入到属性
}
break;
}
}
}
} catch (Exception e) {
}
}
}
}
/**
*完成bean的实例化
*/
privatevoid 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配置文件
*@paramfilename
*/
privatevoid 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");
PropertyDefinition propertyDefinition = new PropertyDefinition(propertyName, propertyref);
beanDefine.getPropertys().add(propertyDefinition);
}
beanDefines.add(beanDefine);
}
}catch(Exception e){
e.printStackTrace();
}
}
/**
*获取bean实例
*@parambeanName
*@return
*/
public Object getBean(String beanName){
returnthis.sigletons.get(beanName);
}
}
十二、Spring 开发的好处
a) 降低组件之间的耦合度,实现软件各层之间的解耦
Controller -- Service -- Dao
b) 可是使用容器提供的众多服务
可使用容器提供的众多服务:事务管理服务(事务传播,无需手工控制事务)、JMS服务、Spring core核心服务、持久化服务、其他……
c) 容器提供单例模式支持,开发人员不再需要自己编写实现代码
d) 容器提供了AOP技术,利用它狠容易实现如权限拦截,运行期监控等功能
e) 容器提供了众多的辅助类,使用这些类,能够加快应用的开发,如:Jdbc Template、Hibernate Template
f) Spring 对于主流的应用框架提供了集成支持,如:集成Hibernate、JPA、Struts等,这样更便于应用的开发
十三、 Spring DI配置文件减肥(Spring2.0 –Spring2.5的升级)
1.@Resource注解
2.注解使Spring 自动扫描和管理bean
扫描路径:<context:component-scan base-package=”cn.itcast” />,将会扫描该包下包括其子包的类
@Component:泛指组件、当组件不好归类的时候,我们可以使用这个注解进行标注
@Service:用于标注业务层组件
@Controller:用于标注控制层组件(如struts中的action)
@Repository:用于标注数据访问组件,即DAO组件
此时bean默认的名称为类全名首写字母小写,也可指定bean名称,如
@Service(“personService”)
下面有几个例子:
service组件的注解
package cn.itcast.service.impl;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.stereotype.Service;
import cn.itcast.dao.PersonDao;
import cn.itcast.service.PersonService;
@Service("personService") @Scope("prototype") //这样可以修改bean作用域
public class PersonServiceBean implements PersonService {
//@Autowired(required=false) @Qualifier("personDaoxxxx")
private PersonDao personDao;
//初始化bean时会执行该方法的注解(ejb3中同样应用)
@PostConstruct
public void init(){
System.out.println("初始化");
}
//销毁bean之前会执行该方法的注解(ejb3中同样应用)
@PreDestroy
public void destory(){
System.out.println("开闭资源");
}
public void setPersonDao(PersonDao personDao) {
this.personDao = personDao;
}
public void save(){
personDao.add();
}
}
dao组件的注解
package cn.itcast.dao.impl;
import org.springframework.stereotype.Repository;
import cn.itcast.dao.PersonDao;
@Repository
public class PersonDaoBean implements PersonDao {
public void add(){
System.out.println("执行PersonDaoBean中的add()方法");
}
}
小结:@PostConstruct 和 @PreDestroy的补充
Spring 容器中的 Bean 是有生命周期的,Spring 允许在 Bean 在初始化完成后以及 Bean 销毁前执行特定的操作,您既可以通过实现 InitializingBean/DisposableBean 接口来定制初始化之后 / 销毁之前的操作方法,也可以通过 <bean> 元素的 init-method/destroy-method 属性指定初始化之后 / 销毁之前调用的操作方法
使用时只需要在方法前标注 @PostConstruct 或 @PreDestroy,这些方法就会在 Bean 初始化后或销毁之前被 Spring容器执行了,我们知道,不管是通过实现 InitializingBean/DisposableBean 接口,还是通过 <bean> 元素的 init-method/destroy-method 属性进行配置,都只能为 Bean 指定一个初始化 / 销毁的方法。但是使用 @PostConstruct 和 @PreDestroy 注释却可以指定多个初始化 / 销毁方法,那些被标注 @PostConstruct 或 @PreDestroy 注释的方法都会在初始化 / 销毁时被执行。
二、实例化Spring容器:
方法一:在类路径下寻找配置文件来实例化容器
ApplicationContext ctx =
new ClassPathXmlApplicationContext(new String[]{“beans.xml”});
方法二:在文件系统路径下寻找配置文件来实例化容器
ApplicationContext ctx =
new FileSystemXmlApplicationContext(new String[]{“d:""beans.xml”});
注:文件可指定多个
可建立单元测试来测试Spring容器的初始化
三、编写Spring 配置文件时,不能出现帮助信息的解决办法—添加schema文件
由于Spring的schema文件位于网络上,如果机器不能连接到网络,那么在写配置文件的时候就无法出现提示信息,解决办法有两种:
1. 让机器上网,Eclipse会自动从网络上下载schema文件并缓存在硬盘上
2.手动添加schema文件,方法如下:
windows->preferences->myeclipse->files and editors->xml->xmlcatalog
a. 我们可以选择将schema文件放到User Specified Entries然后点击‘add’,在出现的窗口中的Key Type中选择URL, 在‘Location’中选择‘File System’,然后在Spring解压目录的dist/resources目录中选择spring-beans-2.5.xsd,
b. 回到设置窗口时候不要急于关闭窗口,应把窗口中的Key Type改为schema location,
c. key改为:
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
四、Spring 配置文件一个小插曲
<bean id=”” name=””></bean>,在这里,id 和name都是为这个bean取的名字,其实这两者意思相同,只是如果选择使用的是id,那么id命名则不能有特殊字符,如果使用的是name则可以使用特殊字符作为name。如
<bean id=”beanId” /> && <bean name=”bean-name”/>
五、Spring容器如何管理bean
首先读取beans.xml里的bean配置所有的id、class的值,作为String形式保存至对应一个Bean,形成bean列表
利用反射机制,将bean列表遍历,生成对象,如下:
package junit.test;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;
/**
*传智传客版容器
*
*/
publicclass ItcastClassPathXMLApplicationContext {
private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();
private Map<String, Object> sigletons = new HashMap<String, Object>();
public ItcastClassPathXMLApplicationContext(String filename){
this.readXML(filename);
this.instanceBeans();
}
/**
*完成bean的实例化
*/
privatevoid 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配置文件
*@paramfilename
*/
privatevoid 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);
beanDefines.add(beanDefine);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
*获取bean实例
*@parambeanName
*@return
*/
public Object getBean(String beanName){
returnthis.sigletons.get(beanName);
}
}
六、Spring的三种实例化Bean方式
1.使用构造器实例化
<bean id="personService" class="cn.itcast.service.impl.PersonServiceBean"></bean>
这种就是利用默认的构造器进行的实例化
2. 静态工厂方法实例化
<bean id="personService2" class="cn.itcast.service.impl.PersonServiceBeanFactory" factory-method="createPersonServiceBean"/>
3. 使用实例工厂方法实例化
<bean id="personServiceFactory" class="cn.itcast.service.impl.PersonServiceBeanFactory"/>
<bean id="personService3" factory-bean="personServiceFactory" factory-method="createPersonServiceBean2"/>
七、bean的作用域-属性scope
singleton:(默认)在每个Spring IOC容器中一个bean定义只有一个对象实例,默认情况下会在容器启动时初始化bean。但我们可以指定bean节点lazy-init=”true” 则表示不需要在容器初始化时候对bean进行初始化,只有在第一次getBean时候进行初始化,如果需要所有的bean都应用延迟初始化,可以在根节点<beans>设置default-lazy-init=”true”(不推荐,不利于观察bean初始化情况)
prototype:每次从容器中获取的bean都是新的对象
request
session
global session
七、Spring管理的bean的生命周期
默认情况下容器初始化的时候对bean进行实例化
如果scope为prototype时,在调用getBean方法时候对bean进行实例化
如果lazy-init为true时,容器初始化时候不会对bean进行实例化
综上所述,Spring管理的bean初始化点根据设定的条件不同而不同
init-method:在bean被实例化的后即会执行的方法
destroy-method:在bean被销毁的时候执行的方法(如果没有手动的销毁该bean,则只有在容器关闭的时候才会销毁)
正常的关闭Spring容器
AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
ctx.close();
八、控制反转IoC 定义:
Public class PersonServiceBean {
Private PersonDao personDao = new PersonDaoBean();
Public void save (Person person) {
personDao.save(person);
}
}
PersonDaoBean是在应用内部创建和维护的,所谓的控制反转就是应用本身不负责依赖对象的创建和维护,依赖对象的创建及维护是由外部容器负责的,这样控制权就由应用转移到了外部容器,控制权的转移就是所谓的反转。
九、依赖注入(Dependency Injection)的定义:
当我们把依赖对象交给外部容器负责创建,那么PersonServiceBean类可以改成如下:
public class PersonServiceBean{
private PersonDao personDao;
//通过构造器参数,让容器把创建好的依赖对象注入进PersonServiceBean,当然也可以使用setter方法进行注入
public PersonServiceBean(PersonDao personDao) {
this.personDao = personDao;
}
Public void save(Person person) {
personDao.save(person);
}
}
所谓的依赖注入就是指:在运行期,由外部容器动态地将依赖对象注入到组件中
十、依赖注入:
1.使用构造器注入
private PersonDao personDao;
private String name;
public PersonServiceBean(PersonDao personDao, String name) {
this.personDao = personDao;
this.name = name;
}
beans.xml配置:
<bean id="personService" class="cn.itcast.service.impl.PersonServiceBean">
<constructor-arg index="0" type="cn.itcast.dao.PersonDao" ref=""></constructor-arg>
<constructor-arg index="1" type="paramValue"></constructor-arg>
</bean>
2.使用setter方法注入
ref形式注入:
<bean id="personService" class="cn.itcast.service.impl.PersonServiceBean">
<property name="personDao" ref="personDaoBean" />
</bean>
可以采用内部bean方式进行注入,不同过ref方式的是,这种内部bean注入对于bean的重用性效果不好:
<bean id="personService" class="cn.itcast.service.impl.PersonServiceBean">
<property name="personDao">
<bean class="cn.itcast.dao.impl.PersonDaoBean" />
</property>
</bean>
bean基本类型的注入:
<bean id="personService" class="cn.itcast.service.impl.PersonServiceBean">
<property name="personDao">
<bean class="cn.itcast.dao.impl.PersonDaoBean" />
</property>
<property name="name" value="itcast" />
<property name="id" value="100" />
</bean>
集合类的注入:
<bean id="personService" class="cn.itcast.service.impl.PersonServiceBean" >
<property name="sets">
<set>
<value>第一个</value>
<value>第二个</value>
<value>第三个</value>
</set>
</property>
<property name="lists">
<list>
<value>第一个list元素</value>
<value>第二个list元素</value>
<value>第三个list元素</value>
</list>
</property>
<property name="properties">
<props>
<prop key="key1">value1</prop>
<prop key="key2">value2</prop>
<prop key="key3">value3</prop>
</props>
</property>
<property name="maps">
<map>
<entry key="key-1" value="value-1" />
<entry key="key-2" value="value-2" />
<entry key="key-3" value="value-3" />
</map>
</property>
</bean>
3.使用Field注入(用于注解方式)
注入依赖对象,可以采用手工装配或者自动装配,在实际应用中建议使用手工装配,因为自动装配会产生未知情况,开发人员无法预见最终装配的结果
1. 手工装配依赖对象
a) 在xml配置文件中,通过在bean节点下配置
b) 在java代码中使用@Autowired或@Resource注解方式进行装配。但我们需要在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">
<!-- 相当于启用解析注解的处理器 -->
<context:annotation-config/>
</beans>
这个配置隐式注册了多个注释进行解析处理的处理器:
注解本身不做任何事情,只是利用这些处理器来达到配置一样的效果
AutowiredAnnotationBeanPostProcessor,
CommonAnnotationBeanPostProcesor,
PersistenceAnnotationBeanPostProcessor,
RquiredAnnotationBeanPostProcessor
注:@Resource注解在spring安装目录的lib/j2ee/common-annotations.jar
jar文件:
dist/spring.jar
lib/Jakarta-commons/commons-logging.jar
lib/aspectjaspectjweaver.jar、aspectjrt.jar//aop
lib/cglib/cglib-nodep-2.1_3.jar
lib/j2ee/common-annotations.jar
在java代码中使用@Autowired或@Resource注解方式进行装配,这两个注解的区别是:
@Autowired默认按类型装配,@Resource默认按照名称装配,当找不到与名称匹配的bean才会匹配的bean才会按类型装配
@Autowired
private PersonDao personDao; //用于字段上
@Autowired
public void setOrderDao(OrderDao orderDao) { //用于属性的setter方法上
this.orderDao = orderDao;
}
@Autowired注解是按类型装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它required属性为false(默认是true),如果我们想按名称装配,可以结合@Qualifier注解一起使用,如下:
@Autowired @Qualifier(“personDaoBean”)
private PersonDao personDao;
如上面的注解,则@Autowired本身是按照类型装配,现在将会按名称装配
@Resource注解和@Actowired一样,也可以标注在字段或者属性的setter方法上,但他默认按照名称装配。名称可以通过@Resource的name属性指定,如果没有指定name属性,当注解标注在字段上,即默认取字段的名称作为bean名称寻找依赖对象,当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找依赖对象。
@Resource(name=”personDaoBean”)
private PersonDao personDao;
注意:如果没有指定name属性,并且暗号默认的名称仍然找不到依赖对象时,“Resource注解会回退到按类型装配,但一旦指定了name属性,就只能按名称装配了
2.自动装配依赖对象
对于自动装配,作为了解
byType:按类型装配,可以根据属性的类型,在容器中寻找跟该类型匹配的bean。如果发现多个,那么将会抛出异常。如果没有找到,即属性值为null。
byName:按名称装配,可以根据属性的名称在容器中寻找跟该属性名相同的bean,如果没有找到,即属性值为null
constructor与byType的方式类似,不同之处在于它应用于构造器参数。如果在容器中没有找到与构造器参数类型一致的bean,那么将会抛出异常
autodetect:通过bean类的自省机制(introspection)来决定是使用constructor还是byType方式进行自动装配。如果发现默认的构造器,那么将使用byType方式
十一、依赖注入的原理
在Spring容器管理bean原理的实例中进行改造,该例子涉及到两个实体类:BeanDefinition{id,class}、PropertyDefinition{name,ref}
package junit.test;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;
/**
*传智传客版容器
*
*/
publicclass ItcastClassPathXMLApplicationContext {
private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();
private Map<String, Object> sigletons = new HashMap<String, Object>();
public ItcastClassPathXMLApplicationContext(String filename){
this.readXML(filename);
this.instanceBeans();
this.injectObject();
}
/**
*为bean对象的属性注入值
*/
privatevoid 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 = sigletons.get(propertyDefinition.getRef());
setter.setAccessible(true);
setter.invoke(bean, value);//把引用对象注入到属性
}
break;
}
}
}
} catch (Exception e) {
}
}
}
}
/**
*完成bean的实例化
*/
privatevoid 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配置文件
*@paramfilename
*/
privatevoid 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");
PropertyDefinition propertyDefinition = new PropertyDefinition(propertyName, propertyref);
beanDefine.getPropertys().add(propertyDefinition);
}
beanDefines.add(beanDefine);
}
}catch(Exception e){
e.printStackTrace();
}
}
/**
*获取bean实例
*@parambeanName
*@return
*/
public Object getBean(String beanName){
returnthis.sigletons.get(beanName);
}
}
十二、Spring 开发的好处
a) 降低组件之间的耦合度,实现软件各层之间的解耦
Controller -- Service -- Dao
b) 可是使用容器提供的众多服务
可使用容器提供的众多服务:事务管理服务(事务传播,无需手工控制事务)、JMS服务、Spring core核心服务、持久化服务、其他……
c) 容器提供单例模式支持,开发人员不再需要自己编写实现代码
d) 容器提供了AOP技术,利用它狠容易实现如权限拦截,运行期监控等功能
e) 容器提供了众多的辅助类,使用这些类,能够加快应用的开发,如:Jdbc Template、Hibernate Template
f) Spring 对于主流的应用框架提供了集成支持,如:集成Hibernate、JPA、Struts等,这样更便于应用的开发
十三、 Spring DI配置文件减肥(Spring2.0 –Spring2.5的升级)
1.@Resource注解
2.注解使Spring 自动扫描和管理bean
扫描路径:<context:component-scan base-package=”cn.itcast” />,将会扫描该包下包括其子包的类
@Component:泛指组件、当组件不好归类的时候,我们可以使用这个注解进行标注
@Service:用于标注业务层组件
@Controller:用于标注控制层组件(如struts中的action)
@Repository:用于标注数据访问组件,即DAO组件
此时bean默认的名称为类全名首写字母小写,也可指定bean名称,如
@Service(“personService”)
下面有几个例子:
service组件的注解
package cn.itcast.service.impl;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.stereotype.Service;
import cn.itcast.dao.PersonDao;
import cn.itcast.service.PersonService;
@Service("personService") @Scope("prototype") //这样可以修改bean作用域
public class PersonServiceBean implements PersonService {
//@Autowired(required=false) @Qualifier("personDaoxxxx")
private PersonDao personDao;
//初始化bean时会执行该方法的注解(ejb3中同样应用)
@PostConstruct
public void init(){
System.out.println("初始化");
}
//销毁bean之前会执行该方法的注解(ejb3中同样应用)
@PreDestroy
public void destory(){
System.out.println("开闭资源");
}
public void setPersonDao(PersonDao personDao) {
this.personDao = personDao;
}
public void save(){
personDao.add();
}
}
dao组件的注解
package cn.itcast.dao.impl;
import org.springframework.stereotype.Repository;
import cn.itcast.dao.PersonDao;
@Repository
public class PersonDaoBean implements PersonDao {
public void add(){
System.out.println("执行PersonDaoBean中的add()方法");
}
}
小结:@PostConstruct 和 @PreDestroy的补充
Spring 容器中的 Bean 是有生命周期的,Spring 允许在 Bean 在初始化完成后以及 Bean 销毁前执行特定的操作,您既可以通过实现 InitializingBean/DisposableBean 接口来定制初始化之后 / 销毁之前的操作方法,也可以通过 <bean> 元素的 init-method/destroy-method 属性指定初始化之后 / 销毁之前调用的操作方法
使用时只需要在方法前标注 @PostConstruct 或 @PreDestroy,这些方法就会在 Bean 初始化后或销毁之前被 Spring容器执行了,我们知道,不管是通过实现 InitializingBean/DisposableBean 接口,还是通过 <bean> 元素的 init-method/destroy-method 属性进行配置,都只能为 Bean 指定一个初始化 / 销毁的方法。但是使用 @PostConstruct 和 @PreDestroy 注释却可以指定多个初始化 / 销毁方法,那些被标注 @PostConstruct 或 @PreDestroy 注释的方法都会在初始化 / 销毁时被执行。
发表评论
-
通过spring开发ActiveMQ简单应用
2011-01-23 20:27 1422使用spring的支持类开发JMS程序可以简化代码,确保开发质 ... -
spring2.5.6+activeMQ5.3.2
2011-01-23 18:58 1975简介: [1] 在介绍ActiveMQ之前,首先简要介绍一下J ... -
IOC控制反转和DI依赖注入区别
2010-08-10 15:54 2338IOC控制反转:说的是创建对象实例的控制权从代码控制剥离到IO ... -
Spring2.5注解实现AOP
2010-08-03 16:23 1006http://hypgr.iteye.com/blog/418 ... -
AOP原理简介
2010-08-03 16:03 21311. 面向切面编程(AOP)原理以及Helloworl ... -
SpringAOP结合MemCached做缓存的设想
2010-07-08 08:54 13261, 给DAO的方法上加SpringAOP的Around通知, ... -
Spring jdbc 对象Mapper的简单封装
2010-07-07 14:06 2297一般查询实体的时候,都需要这么使用: /** *//** ... -
spring的通用事务管理机制
2010-05-16 18:28 1191<tx:advice id="service ... -
Spring 的优秀工具类盘点
2010-04-26 21:43 1062http://www.ibm.com/developerwor ... -
Struts与Spring整合
2010-04-19 00:21 1055如果需要使用第三方MVC框架,则不能在web.xml文件中配置 ...
相关推荐
在本例中,可能有一个名为`spring-ioc-anno`的包,其中包含着使用注解配置的Spring bean。 为了启动Spring容器并运行应用程序,我们可以创建一个主类,使用`ApplicationContext`来加载配置并获取bean。例如: ```...
Spring5 框架 ---- IOC容器 ---- 代码 Spring5 框架 ---- IOC容器 ---- 代码 Spring5 框架 ---- IOC容器 ---- 代码 Spring5 框架 ---- IOC容器 ---- 代码 Spring5 框架 ---- IOC容器 ---- 代码 Spring5 框架 ---- ...
什么是spring,spring核心,spring优点,spring体系结构, 入门案例,DI基础,核心API,文档内附代码
**Spring IoC简介** Spring框架的核心特性之一是Inversion of Control(IoC),也被称为依赖注入(Dependency Injection)。IoC是一种设计模式,它将对象之间的依赖关系从代码中解耦出来,转交给一个外部容器(在...
Spring IoC 和 DI 注解开发 Spring IoC 和 DI 注解开发概述 Spring IoC(Inverse of Control,控制反转)是一种软件设计模式,它将传统的控制权从应用程序转移到框架中,使得应用程序更加灵活和可扩展。DI...
在Spring中,通常通过以下三种注解实现IoC: - `@Autowired`:自动装配,Spring会根据类型或名称找到合适的bean进行注入。 - `@Qualifier`:当有多个相同类型的bean时,用于指定注入哪一个。 - `@Resource`:基于...
在Spring中,依赖注入(Dependency Injection,简称DI)是核心特性,而注解(Annotation)则是实现DI的一种现代化方式。"spring-demo10-注解-IOC.zip"这个压缩包文件很显然包含了关于Spring框架如何使用注解进行依赖...
### Spring IOC与DI注解开发知识点详解 #### 一、Spring框架概述 Spring是一个开源的Java平台框架,它提供了一种全面的编程模型,并且支持从底层的数据访问/集成到应用层的服务抽象。Spring框架的核心特性包括依赖...
第一个spring IOC例子(非maven) 方法步骤: 1、下载spring包,提取core,bean,context,expression 四大基础jar http://repo.spring.io/release/org/springframework/spring/ 2、下载common-logging jar ...
**Spring Ioc 实现原理详解** Spring Ioc(Inversion of Control,控制反转)是Spring框架的核心特性之一,它改变了传统应用程序中对象的创建和管理方式。在传统的软件设计中,对象的创建和依赖关系的维护通常由...
JAVAEE之Spring IoC&DI Spring IoC(Inversion of Control,即控制反转)是Spring框架的核心机制之一,它提供了一种解耦合的方式,使得应用程序的各个组件之间能够松散耦合,提高了系统的灵活性和可维护性。 在传统...
spring-core:核心模块 依赖注入IOC和DI的最基本实现 spring-beans:Bean工厂与装配 spring-context:上下文,即IOC容器 spring-context-support:对IOC的扩展,以及IOC子容器 spring-context-indexer:类管理组件和...
dijon, 在Javascript中,由Robotlegs和Swiftsuspenders激发的,ioc/di框架 DIJON框架 Dijon是用于Javascript的IOC和DI微框架。 最初它是一个Robotlegs端口,但却偏离了一些完全不同的地方。 它仍然受到Robotlegs的...
**Spring-IOC实例详解** Spring框架是Java开发中不可或缺的一部分,尤其在企业级应用中,其Inversion of Control(IoC)容器是其核心特性之一。IoC,也被称为依赖注入(Dependency Injection,DI),是一种设计模式...
标题 "Spring IOC" 描述了我们讨论的核心主题——Spring 框架中的依赖注入(Inversion of Control,简称 IOC)机制。Spring 是一个广泛应用的 Java 应用开发框架,其核心特性之一就是IOC,它极大地简化了软件组件...
Spring Ioc源码分析系列--@Autowired注解的实现原理 @ Автоwired注解是 Spring Framework 中的一个重要组件,它提供了自动装配的功能,能够将 Bean 之间的依赖关系自动解析和注入。今天,我们将深入探讨 @...
### Spring IoC与注解依赖注入详解 #### 一、Spring框架简介 Spring框架是由Rod Johnson创建的一个开源项目,最初是为了解决企业级应用开发中的复杂性问题而诞生的。Spring框架的核心特性包括IoC(Inversion of ...
Spring IOC和DI实现原理及实例解析 Spring IOC(Inversion of Control,控制反转)是Spring框架的基础,它简单地说就是创建对象由以前的程序员调用new构造方法,变成了交由Spring创建对象。DI(Dependency Inject,...
Spring框架约束资源与步骤欢迎大家使用,Spring框架约束文件 sspring-core-4.1.6.RELEASE-sources.jar spring-core.jar 这个jar...如果应用只需基本的IoC/DI支持,引入spring-core.jar及spring-beans.jar文件就能了。
这个jar文件"Spring-ioc-jar"包含了实现Spring IOC功能所需的关键类和接口,是学习和使用Spring IOC技术的基础。 Spring框架的IOC容器是其核心组件,主要由`ApplicationContext`和`BeanFactory`两个接口代表。`...