1.Spring优点
- Spring的IOC降低了业务对象替换的复杂性,提高了解耦;
- Spring的AOP支持允许将通用的任务如安全、事务、日志等进行集中式处理,提高了复用。
2.Spring管理Bean-xml
Spring IOC核心容器理论很简单:Spring容器就是一个大工厂,所有对象都会当成对象,Spring把一切对象统称为Bean。只要是一个java类,就当成javaBean处理。
A对象需要调用B对象的方法,称之为依赖。以下是一个Person类依赖Axe对象的例子。
public class Axe
{
public String chop()
{
return "使用斧头砍柴";
}
}
public class Person
{
private Axe axe;
// 设值注入所需的setter方法
public void setAxe(Axe axe)
{
this.axe = axe;
}
public void useAxe()
{
System.out.println("我打算去砍点柴火!");
// 调用axe的chop()方法,
// 表明Person对象依赖于axe对象
System.out.println(axe.chop());
}
}
Spring中是怎么管理这些Bean(即对象)的呢?
答案:.xml文件
<?xml version="1.0" encoding="GBK"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> <!-- 配置名为person的Bean,其实现类是org.crazyit.app.service.Person类 --> <bean id="person" class="codeEETest.Person"> <!-- 控制调用setAxe()方法,将容器中axe Bean作为传入参数 --> <property name="axe" ref="axe"/> </bean> <!-- 配置名为axe的Bean,其实现类是org.crazyit.app.service.Axe类 --> <bean id="axe" class="codeEETest.Axe"/> <!-- 配置名为win的Bean,其实现类是javax.swing.JFrame类 --> <bean id="win" class="javax.swing.JFrame"/> <!-- 配置名为date的Bean,其实现类是java.util.Date类 --> <bean id="date" class="java.util.Date"/> </beans>
事实上,配置文件中的<bean.../>元素默认以反射的方式调用该类的无参构造器。如:
<bean id="person" class="codeEETest.Person">
Spring底层会执行如下代码:
String idStr="..."; //即将"person"传入
//解析classStr="codeEETest.Person"的字符串
String classStr="...";
Class clz=Class.forName(ClassStr);
Object obj=clz.newInstance();
//container代表Spring容器
container.put(idStr, obj);
以id属性的值为key,将该对象放入到Spring容器中。
结论:
在Spring配置文件中配置bean时,class属性必须为类的全限定名,不能是接口,不能是抽象类(除非有特殊配置),否则Spring无法使用反射创建该类。
对于<property.../>子元素,Spring框架以反射的方式执行一次setter方法。
<bean id="person" class="codeEETest.Person">
<!-- 控制调用setAxe()方法,将容器中axe Bean作为传入参数 -->
<!-- 控制调用setAxe()方法,将容器中axe Bean作为传入参数 -->
<property name="axe" ref="axe"/>
</bean>
说明:Spring以反射方式执行personBean的setAxe()方法
String nameStr = "...";//name属性即"axe"
String refStr="..."; //ref属性"axe"
String setterName = "set"+nameStr.substring(0,1).toUpperCase()+nameStr.substring(1);
//获得容器中ref指向的bean,该bean作为参数传入
Object paramBean = container.get(refStr);
//clz是之前获得的bean字节码
Method setter = clz.getMethod(setterName,paramBean.getClass());
//obj是之前获得的
setter.invoke(obj,paramBean);
说明:property属性详解:
- 如果传入参数是基本数据类型或其包装类、String类型,则使用value属性指定传入的参数
- 如果是容器中其他的bean对象,则使用ref属性指定传入的参数。
-----------------------------------------------------------------------------------------------------
3.创建Spring容器并访问bean
接下来,就可以使用Spring容器来访问容器中的Bean,ApplicationContext是Spring容器中最常用的接口。有两个实现类:
- ClassPathXmlApplicationContext:从类加载器路径下搜索配置文件,并根据配置文件创建Spring容器。(常用)
- FileSystemXMLApplicationContext:从文件系统...(不常用)
代码如下:
package codeEETest;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class BeanTest
{
public static void main(String[] args)throws Exception
{
// 创建Spring容器
ApplicationContext ctx = new
ClassPathXmlApplicationContext("codeEETest/beans.xml");
// 获取id为person的Bean
Person p = ctx.getBean("person" , Person.class);
// 调用useAxe()方法
p.useAxe();
}
}
//文件结构
codeEETest
----Axe.java
----Person.java
----BeanTest.java
----bean.xml
//效果
我打算去砍点柴火!
使用斧头砍柴
说明:Spring容器获得Bean有两种方式
- Object getBean(String id): 获得bean后需要强转
- T getBean(String name,class<T> requiredType) 类似示例的,不需转换
说明:需要springlib的21个jar包和commons-logging.jar
//文件结构
codeEETest
----Axe.java
----Person.java
----BeanTest.java
----bean.xml
//效果
我打算去砍点柴火!
使用斧头砍柴
- Object getBean(String id): 获得bean后需要强转
- T getBean(String name,class<T> requiredType) 类似示例的,不需转换