1.Spring装配一个bean
在前一章中已涉及到此知识点,通俗的来讲:在建立People实体之后,在beans.xml 中配置,然后在实现类中调用 beans.xml文件,即装配完成,调用默认的构造方法。
-
建立实体 (People.java) 类
public class People { private int id; private String name; private int age; // 构造方法 public People() { super(); } public People(int id, String name, int age) { super(); this.id = id; this.name = name; this.age = age; } }
-
配置beans.xml 文件
<bean id="people" class="com.java1234.entity.People"></bean>
-
调用beans.xml 文件
ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml");
2.依赖注入
- 1. 属性注入;
- 2. 构造函数注入;(通过类型;通过索引;联合使用)
- 3. 工厂方法注入;(非静态工厂,静态工厂)
- 4. 泛型依赖注入;(参考后面 Spring4 整合 Hibernate4 记录)
<!-- 装配 --> <bean id="people" class="com.java1234.entity.People"></bean> <!-- 属性注入--> <bean id="people2" class="com.java1234.entity.People"> <property name="id" value="1"></property> <property name="name" value="张三"></property> <property name="age" value="11"></property> </bean>
<!-- 构造函数注入(通过类型)--> <bean id="people3" class="com.java1234.entity.People"> <constructor-arg type="int" value="2"></constructor-arg> <constructor-arg type="String" value="李四"></constructor-arg> <constructor-arg type="int" value="22"></constructor-arg> </bean> <!-- 构造函数注入(通过索引)--> <bean id="people4" class="com.java1234.entity.People"> <constructor-arg index="0" value="3"></constructor-arg> <constructor-arg index="1" value="王五"></constructor-arg> <constructor-arg index="2" value="55"></constructor-arg> </bean> <!-- 构造函数注入(类型索引联合使用)--> <bean id="people5" class="com.java1234.entity.People"> <constructor-arg index="0" type="int" value="4"></constructor-arg> <constructor-arg index="1" type="String" value="招六"></constructor-arg> <constructor-arg index="2" type="int" value="66"></constructor-arg> </bean>
<!-- 工厂方法注入(非静态工厂)--> <bean id="peopleFactory" class="com.java1234.factory.PeopleFactory"></bean> <bean id="people6" factory-bean="peopleFactory" factory-method="createPeople"></bean> <!-- 工厂方法注入(静态工厂)--> <bean id="people7" class="com.java1234.factory.PeopleFactory2" factory-method="createPeople"></bean>public class Test2 { public static void main(String[] args) { ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml"); People people=(People)ac.getBean("people"); System.out.println(people); // 属性注入 People people2=(People)ac.getBean("people2"); System.out.println(people2); // 构造方法注入 People people3=(People)ac.getBean("people3"); System.out.println(people3); People people4=(People)ac.getBean("people4"); System.out.println(people4); People people5=(People)ac.getBean("people5"); System.out.println(people5); // 工厂方法注入 People people6=(People)ac.getBean("people6"); System.out.println(people6); People people7=(People)ac.getBean("people7"); System.out.println(people7); } }
3.注入参数
-
1. 基本类型值:参见上一节属性注入
-
2. 注入 bean;
<!-- 在 people2 里面注入 dog1 --> <bean id="dog1" class="com.java1234.entity.Dog"> <property name="name" value="Jack"></property> </bean> <bean id="people2" class="com.java1234.entity.People"> <property name="id" value="1"></property> <property name="name" value="张三"></property> <property name="age" value="11"></property> <property name="dog" ref="dog1"></property> <!-- bean 注入 ,在 People.java 类中声明 dog类--> </bean>
-
3. 内部 bean;
<bean id="people3" class="com.java1234.entity.People"> <property name="id" value="1"></property> <property name="name" value="张三"></property> <property name="age" value="11"></property> <property name="dog"> <bean class="com.java1234.entity.Dog"> <property name="name" value="Tom"></property> </bean> </property> </bean>
-
4. null 值;
<bean id="people4" class="com.java1234.entity.People"> <property name="id" value="1"></property> <property name="name" value="张三"></property> <property name="age" value="11"></property> <property name="dog"> <null></null> </property> </bean>
-
5. 级联属性;
<bean id="people5" class="com.java1234.entity.People"> <property name="id" value="1"></property> <property name="name" value="张三"></property> <property name="age" value="11"></property> <property name="dog.name" value="Jack2"></property>
<!-- 因为此处用到了dog的属性,需要在声明的时候new一个dog对象。( private Dog dog = new Dog(); ) --> </bean> -
6. 集合类型属性;
<bean id="people6" class="com.java1234.entity.People"> <property name="id" value="1"></property> <property name="name" value="张三"></property> <property name="age" value="11"></property> <property name="dog" ref="dog1"></property> <property name="hobbies"> <list> <!-- list集合,可重复 --> <value>唱歌</value> <value>跳舞</value> </list> </property> <property name="loves"> <set> ·<!-- set集合,不可重复 --> <value>唱歌2</value> <value>跳舞2</value> </set> </property> <property name="works"> <map> <!-- Map键值对 --> <entry> <key><value>上午</value></key> <value>写代码</value> </entry> <entry> <key><value>下午</value></key> <value>测试代码</value> </entry> </map> </property> <property name="addresses"> <props> <!-- props 输入结果和Map类似,props 主要用于一些系统的配置--> <prop key="address1">aaaaa</prop> <prop key="address2">bbbbb</prop> </props> </property> </bean>
private Dog dog; private List<String> hobbies=new ArrayList<String>(); private Set<String> loves=new HashSet<String>(); private Map<String,String> works=new HashMap<String,String>(); private Properties addresses=new Properties();
4.自动装配
通过配置 default-autowire 属性(byName,byType,constructor),Spring IOC 容器可以自动为程序注入 bean;默认是 no,不启用自动装配;
<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.xsd" default-autowire="constructor"> <!-- 在此处设置 -->
- byName:通过名称进行自动匹配,根据类中声明的属性名称选择注入的值;
// People.java private Dog dog1;
<!-- beans.xml --> <bean id="dog1" class="com.java1234.entity.Dog"> <property name="name" value="Tom"></property> </bean> <bean id="dog2" class="com.java1234.entity.Dog"> <property name="name" value="Jack"></property> </bean> <bean id="people1" class="com.java1234.entity.People"> <property name="id" value="1"></property> <property name="name" value="张三"></property> <property name="age" value="11"></property> </bean>
// 测试 public void test1() { private ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml"); People people=(People)ac.getBean("people1"); System.out.println(people); }
结果是:取出的狗名叫:Tom, 注意看People.java里面声明的狗是 dog1.
.
- byType:根据类型进行自动匹配,class="com.java1234.entity.Dog ;
- constructor:和 byType 类似,只不过它是根据构造方法注入而言的,根据类型,自动注入;
建议:自动装配机制慎用,它屏蔽了装配细节,容易产生潜在的错误;
5.方法注入
Spring bean 作用域默认是 单例 singleton; 可以通过配置 prototype ,实现多例; 方法注入 lookup-method .
- 默认单例 :每次获取的实例都是一样的
System.out.println(ac.getBean("dog")=ac.getBean("dog")); //返回true
- 配置多例:每次获取的实例是不一样的 ( scope="prototype" )
<bean id="dog" class="com.java1234.entity.Dog" scope="prototype"> <property name="name" value="Jack"></property> </bean>
System.out.println(ac.getBean("dog")=ac.getBean("dog")); //返回false
注:当把dog bean作为属性注入给其他bean是,是同一条狗,而不是新的!所以可以使用lookup-method 方法注入修改
- bean注入时lookup-method
<bean id="dog" class="com.java1234.entity.Dog" scope="prototype"> <property name="name" value="Jack"></property> </bean> <bean id="people1" class="com.java1234.entity.People"> <property name="id" value="1"></property> <property name="name" value="张三"></property> <property name="age" value="11"></property> <lookup-method name="getDog" bean="dog"/> <!-- lookup-method --> </bean>
注:此时要将getDog的方法改成抽象方法
public abstract class People { private Dog dog; public abstract Dog getDog(); public void setDog(Dog dog) { this.dog = dog; } }
6.方法替换
假如,people1 有一条叫 Tom 的狗,people2 有一条叫 Jack 的狗,现在 people1 想要名叫 Jack 即 people2 的狗,即可用方法替换来实现。
此时需要将 people2 的 getDog() 方法替换成people1 的。
- people2 实现接口 MethodReplacer
public class People2 implements MethodReplacer { @Override public Object reimplement(Object arg0, Method arg1, Object[] arg2) throws Throwable { Dog dog=new Dog(); dog.setName("Tom"); return dog; } }
<bean id="people2" class="com.java1234.entity.People2"></bean> <bean id="people1" class="com.java1234.entity.People"> <property name="id" value="1"></property> <property name="name" value="张三"></property> <property name="age" value="11"></property> <replaced-method name="getDog" replacer="people2"></replaced-method> <!-- 用people2里面的reimplement来替换people1里面的getDog方法 --> </bean>
7.Bean之间的关系
- 1. 继承:抽象的Bean可以定义一些公共的属性和方法( abstract="true" )
<!-- bstract="true" --> <bean id="abstractPeople" class="com.java1234.entity.People" abstract="true"> <property name="className" value="高三5班"></property> <property name="age" value="19"></property> </bean> <!-- parent="abstractPeople" --> <bean id="lisi" parent="abstractPeople"> <!-- 无需class,可不建立实体类 --> <property name="id" value="2"></property> <property name="name" value="李四"></property> <property name="age" value="20"></property> <!-- 属性可重写 --> </bean> <!-- 结果是:id=2——李四——高三5班——20岁 -->
- 2. 依赖:未加入依赖的时候,按顺序执行bean;加入依赖后,会先去执行依赖的 bean ( depends-on="autority" ),可用于权限设置
<!-- depends-on="autority" --> <bean id="zhangsan" parent="abstractPeople" depends-on="autority"> <property name="id" value="1"></property> <property name="name" value="张三"></property> </bean> <bean id="autority" class="com.java1234.service.Authority"></bean>
- 3. 引用:引用bean (ref),可参照前面的内容
8.Bean的作用范围
- 1. singleton:Spring ioc 容器中仅有一个 Bean 实例,Bean 以单例的方式存在;
- 2. prototype:每次从容器中调用 Bean 时,都返回一个新的实例;
- 3. request: 每次 HTTP 请求都会创建一个新的 Bean;
- 4. session: 同一个 HTTP Session 共享一个 Bean;
- 5. global session: 同一个全局 Session 共享一个 Bean,一般用于 Portlet 应用环境;
- 6. application: 同一个 Application 共享一个 Bean;
<!-- scope="singleton/prototype/....." --> <bean id="dog" class="com.java1234.entity.Dog" scope="singleton"> <property name="name" value="jack"></property> </bean>