0


Spring1~~~

快速入门

javaBean规范要有set方法,底层反射赋值

  1. <!-- id表示在该java对象在spring容器中的id-->
  2. <bean class="spring.bean.Monster" id="monster01">
  3. <property name="Id" value="100"/>
  4. <property name="name" value="牛魔王"/>
  5. <property name="skill" value="芭蕉扇"/>
  6. </bean>
  1. public class SpringBeanTest {
  2. @Test
  3. public void getMonster() {
  4. ApplicationContext ioc =
  5. new ClassPathXmlApplicationContext("beans.xml");
  6. //第一种
  7. //Object monster01 = ioc.getBean("monster01");
  8. Monster monster01 = (Monster) ioc.getBean("monster01");
  9. System.out.println(monster01);
  10. //第二种
  11. Monster monster011 = ioc.getBean("monster01", Monster.class);
  12. System.out.println(monster011);
  13. //类加载路径
  14. //D:\Atest\spring\out\production\spring
  15. File file = new File(this.getClass().getResource("/").getPath());
  16. System.out.println(file);
  17. }

分析

beanDefinitionMap

table存放bean对象信息

ConcurrentHashMap$Node

singletonObjects

真正创建的对象

beanDefinitionNames

先在beanDefintionMap中查找,再判断是否单例,是的话在单例池中找到返回,否则通过反射创建再返回

实现简单基于XML配置程序

  1. public class HspApplicationContext {
  2. private ConcurrentHashMap<String,Object> singletonObejcts = new ConcurrentHashMap();
  3. public HspApplicationContext(String iocBeanXmlFile) throws Exception {
  4. //加载类路径
  5. String path = this.getClass().getResource("/").getPath();
  6. SAXReader reader = new SAXReader();
  7. //得到Document对象
  8. Document document = reader.read(path + iocBeanXmlFile);
  9. //得到rootDocument
  10. Element rootElement = document.getRootElement();
  11. Element bean = (Element) rootElement.elements("bean").get(0);
  12. //获取第一个bean的 id 和 全路径
  13. String id = bean.attributeValue("id");
  14. String classFullPath = bean.attributeValue("class");
  15. //获取第一个bean的属性
  16. List<Element> property = bean.elements("property");
  17. Integer monsterId = Integer.parseInt(property.get(0).attributeValue("value"));
  18. String name = property.get(1).attributeValue("value");
  19. String skill = property.get(2).attributeValue("value");
  20. //使用反射创建对象,属性赋值
  21. Class<?> cls = Class.forName(classFullPath);
  22. Monster o = (Monster)cls.newInstance();
  23. o.setId(monsterId);
  24. o.setName(name);
  25. o.setSkill(skill);
  26. //创建好的对象放入单例池
  27. singletonObejcts.put(id, o);
  28. }
  29. public Object getBean(String id) {
  30. return singletonObejcts.get(id);
  31. }
  32. }

Spring原生容器底层结构

id分配规则

bean不带id,系统会默认分配id,分配id的规则是 全类名#0, 全类名#1 这样的规则来分配id

  1. <bean class="spring.bean.Monster">
  2. </bean>
  3. <bean class="spring.bean.Monster">
  4. </bean>
  1. Monster monster01 = ioc.getBean("spring.bean.Monster#0", Monster.class);

Spring管理Bean - IOC

基于XML配置Bean

底层使用反射来创建实例,默认会调用无参构造方法

bean底层存放到Map<String**(id)**,Object**(bean)**>

解析xml配置文件就会创建xml里设置的所有对象

new ClassPathXmlApplicationContext("s1.xml",""s2.xml");可以写多个xml文件,可变长

不一定是自定义的bean,可以是系统存在的类,如Date

BeanFactory是ioc容器的顶级接口,负责创建Bean对象,是一个工厂,也可以用BeanFactory代替ApplicationContext

通过id获取bean

  1. <bean class="spring.bean.Monster" id="monster01">
  2. </bean>
  1. Monster monster011 = ioc.getBean("monster01", Monster.class);
  2. Object monster012 = ioc.getBean("monster01");

通过类型获取bean

  1. public void getBeanByType() {
  2. ApplicationContext ioc =
  3. new ClassPathXmlApplicationContext("beans.xml");
  4. Monster bean = ioc.getBean(Monster.class);
  5. System.out.println(bean);
  6. }

要求ioc容器中的同一个类的bean只能有一个

应用场景:比如XxxAction/Servlet/Controller, 或 XxxService 在一个线程中只需要一个对象实例(单例)的情况

通过C命名空间配置bean

简化构造器

不使用C命名空间

** 1. constructor-arg标签可以指定使用构造器的参数
2. index表示构造器的第几个参数 从0开始计算的
3. 除了可以通过index 还可以通过 name / type 来指定参数方式
4. 类的构造器,不能有完全相同类型和顺序的构造器,所以可以通过type来指定**

  1. <bean id="monster03" class="spring.bean.Monster">
  2. <constructor-arg value="200" index="0"/>
  3. <constructor-arg value="白骨精" index="1"/>
  4. <constructor-arg value="吸人血" index="2"/>
  5. </bean>
  6. <bean id="monster04" class="spring.bean.Monster">
  7. <constructor-arg value="200" name="monsterId"/>
  8. <constructor-arg value="白骨精" name="name"/>
  9. <constructor-arg value="吸人血" name="skill"/>
  10. </bean>
  11. <bean id="monster05" class="spring.bean.Monster">
  12. <constructor-arg value="300" type="java.lang.Integer"/>
  13. <constructor-arg value="白骨精~" type="java.lang.String"/>
  14. <constructor-arg value="吸人血~" type="java.lang.String"/>
  15. </bean>

**使用C命名空间 **

  1. <bean id="monster01" class="spring.bean.Monster"
  2. c:_0="200" c:_0="白骨精" c:_0="吸人血"/>
  3. <bean id="monster01" class="spring.bean.Monster"
  4. c:monsterId="200" c:name="白骨精" c:skill="吸人血"/>

通过P命名空间配置bean

基于set方法,进行简化

  1. //将光标放在p , 输入alt+enter , 就会自动的添加xmlns
  2. <bean class="spring.bean.Monster" id="monster01"
  3. p:id="100"
  4. p:name="红孩儿"
  5. p:skill="吐火"
  6. p:birth-ref="birthBean"
  7. />
  8. <bean id="birthBean" class="java.util.Date"/>

通过util:list进行配置bean

普通做法,如果数据共享,太繁琐,需要复用

  1. <!--配置Bookstore-->
  2. <bean class="spring.bean.Bookstore" id="bookstore1">
  3. <property name="bookList">
  4. <list>
  5. <value>三国演义</value>
  6. <value>红楼梦</value>
  7. <value>西游记</value>
  8. <value>水浒传</value>
  9. </list>
  10. </property>
  11. </bean>
  12. <bean class="spring.bean.Bookstore" id="bookstore2">
  13. <property name="bookList">
  14. <list>
  15. <value>三国演义</value>
  16. <value>红楼梦</value>
  17. <value>西游记</value>
  18. <value>水浒传</value>
  19. </list>
  20. </property>
  21. </bean>

使用util:list指定id,直接ref引用过来

  1. <!--定义util:list-->
  2. <util:list id="myBookList">
  3. <value>三国演义</value>
  4. <value>红楼梦</value>
  5. <value>西游记</value>
  6. <value>水浒传</value>
  7. </util:list>
  8. <!--配置Bookstore-->
  9. <bean class="spring.bean.Bookstore" id="bookstore1">
  10. <property name="bookList" ref="myBookList"/>
  11. </bean>
  12. <bean class="spring.bean.Bookstore" id="bookstore2">
  13. <property name="bookList" ref="myBookList"/>
  14. </bean>

通过外部属性文件配置Bean

在src目录下新建xx.properties

my.properties

  1. monsterId=1000
  2. name=jack
  3. skill=hello

** 如果v是中文,可以转成unicode编码**

  1. <!--
  2. 文件提示修改成 all problems,引入namespace
  3. location="classpath:my.properties" 表示指定属性文件的位置
  4. -->
  5. <context:property-placeholder location="classpath:my.properties"/>
  6. <!--
  7. 通过属性文件给monster对象的属性赋值
  8. 属性名通过${属性名},属性名就是my.properties文件中k=v的k
  9. -->
  10. <bean class="spring.bean.Monster" id="monster100">
  11. <property name="id" value="${monsterId}"/>
  12. <property name="name" value="${name}"/>
  13. <property name="skill" value="${skill}"/>
  14. </bean>

Bean信息重用(继承)

  1. <bean id="monster10" class="spring.bean.Monster">
  2. <property name="monsterId" value="10"/>
  3. <property name="name" value="蜈蚣精"/>
  4. <property name="skill" value="蜇人"/>
  5. </bean>
  6. <!--
  7. 1. 配置Monster对象
  8. 2.但是这个对象的属性值和 id="monster10"对象属性一样
  9. 3.parent="monster10" 指定当前这个配置的对象的属性值从 id=monster10的对象来
  10. -->
  11. <bean id="monster11"
  12. class="spring.bean.Monster"
  13. parent="monster10"/>
  14. <bean id="monster12" class="spring.bean.Monster" abstract="true">
  15. <property name="monsterId" value="10"/>
  16. <property name="name" value="蜈蚣精"/>
  17. <property name="skill" value="蜇人"/>
  18. </bean>
  19. <bean id="monster13"
  20. class="spring.bean.Monster"
  21. parent="monster12"/>

1. 如果bean指定了 abstract="true", 表示该bean对象, 是用于被继承
2. 本身这个bean就不能被获取/实例化

基于XML自动装配

要有set方法

DAO层

  1. public class OrderDao {
  2. //方法。。。
  3. public void saveOrder() {
  4. System.out.println("保存 一个订单...");
  5. }
  6. }

Service层

  1. public class OrderService {
  2. //OrderDao属性
  3. private OrderDao orderDao;
  4. //getter
  5. public OrderDao getOrderDao() {
  6. return orderDao;
  7. }
  8. //setter
  9. public void setOrderDao(OrderDao orderDao) {
  10. this.orderDao = orderDao;
  11. }
  12. }

Controller层

  1. public class OrderAction {
  2. //属性OrderService
  3. private OrderService orderService;
  4. //getter
  5. public OrderService getOrderService() {
  6. return orderService;
  7. }
  8. //setter
  9. public void setOrderService(OrderService orderService) {
  10. this.orderService = orderService;
  11. }
  12. }

xml

  1. <!--配置OrderDao对象-->
  2. <bean class="spring.dao.OrderDao" id="orderDao"/>
  3. <!--配置OrderService对象
  4. 1. autowire="byType" 表示 在创建 orderService时
  5. 通过类型的方式 给对象属性 自动完成赋值/引用
  6. 2. 比如OrderService 对象有 private OrderDao orderDao
  7. 3. 就会在容器中去找有没有 OrderDao类型对象
  8. 4. 如果有,就会自动的装配, 老师提示如果是按照 byType 方式来装配, 这个容器中,不能有两个
  9. 的OrderDao类型对象
  10. 5. 如果你的对象没有属性, autowire就没有必要写
  11. 6. 其它类推..
  12. 7. 如果我们设置的是 autowire="byName" 表示通过名字完成自动装配
  13. 8. 比如下面的 autowire="byName" class="com.hspedu.spring.service.OrderService"
  14. 1) 先看 OrderService 属性 private OrderDao orderDao
  15. 2) 再根据这个属性的setXxx()方法的 xxx 来找对象id
  16. 3) public void setOrderDao() 就会找id=orderDao对象来进行自动装配
  17. 4) 如果没有就装配失败
  18. -->
  19. <bean autowire="byName" class="spring.service.OrderService"
  20. id="orderService"/>
  21. <!--配置OrderAction-->
  22. <bean autowire="byName" class="spring.web.OrderAction" id="orderAction"/>

使用byName装配,id名要与set方法名(去掉set,首字母小写)一致

在OrderAction类中,setOrderService方法名更改, class="spring.service.OrderService"的id也要更改,根据方法名找对象id

注入bean对象

** 简单类型使用value(除Date),非简单类型使用ref**

Set注入

service层

  1. public class MemberServiceImpl {
  2. private MemberDAOImpl memberDAO;
  3. public MemberServiceImpl() {
  4. System.out.println("MemberServiceImpl() 构造器被执行");
  5. }
  6. public MemberDAOImpl getMemberDAO() {return memberDAO;}
  7. public void setMemberDAO(MemberDAOImpl memberDAO) {this.memberDAO = memberDAO;}
  8. public void add() {
  9. System.out.println("MemberServiceImpl add() 被调用..");
  10. memberDAO.add();
  11. }
  12. }

dao层

  1. public class MemberDAOImpl {
  2. public MemberDAOImpl() {
  3. System.out.println("MemberDAOImpl 构造器被执行...");
  4. }
  5. public void add() {
  6. System.out.println("MemberDAOImpl add()方法被执行");
  7. }
  8. }

name规则:必须提供set方法,去掉set,第一个字母小写

**外部bean **

  1. <bean class="spring.dao.MemberDAOImpl" id="memberDAO"/>
  2. <bean class="spring.service.MemberServiceImpl" id="memberService">
  3. <property name="memberDAO" ref="memberDAO"/>
  4. </bean>

**内部bean **

  1. <bean class="spring.service.MemberServiceImpl" id="memberService">
  2. <property name="memberDAO">
  3. <bean class="spring.dao.MemberDAOImpl"/>
  4. </property>
  5. </bean>

构造注入

三种写法

Set注入专题

注入集合/数组/Proiperties

list有序可重复

set无需不可以重复

Map

  1. <!--配置Master-->
  2. <bean class="spring.bean.Master" id="master">
  3. <property name="name" value="太上老君"/>
  4. <!--对List属性进行配置-->
  5. <property name="monsterList">
  6. <list>
  7. <!--引入其他bean-->
  8. <ref bean="monster01"/>
  9. <ref bean="monster02"/>
  10. <!--内部bean-->
  11. <bean class="spring.bean.Monster">
  12. <property name="name" value="老鼠精"/>
  13. <property name="Id" value="100"/>
  14. <property name="skill" value="吃粮食"/>
  15. </bean>
  16. </list>
  17. </property>
  18. <!--对Map属性进行配置-->
  19. <property name="monsterMap">
  20. <map>
  21. <entry>
  22. <key>
  23. <value>monster01</value>
  24. </key>
  25. <ref bean="monster01"/>
  26. </entry>
  27. <entry>
  28. <key>
  29. <value>monster02</value>
  30. </key>
  31. <ref bean="monster02"/>
  32. </entry>
  33. </map>
  34. </property>
  35. <!--给set属性赋值-->
  36. <property name="monsterSet">
  37. <set>
  38. <ref bean="monster01"/>
  39. <ref bean="monster02"/>
  40. </set>
  41. </property>
  42. <!--
  43. 给数组属性赋值
  44. array标签中使用 value 还是 bean , ref .. 要根据你的业务决定
  45. -->
  46. <property name="monsterName">
  47. <array>
  48. //数组是基本类型
  49. <value>小妖怪</value>
  50. <value>大妖怪</value>
  51. //数组是对象类型,需要先给这个对象配置bean
  52. <ref bean="w1"/>
  53. <ref bean="w2"/>
  54. </array>
  55. </property>
  56. <!--给Properties属性赋值 结构k(String)-v(String)-->
  57. <property name="pros">
  58. <props>
  59. <prop key="username">root</prop>
  60. <prop key="password">123456</prop>
  61. <prop key="ip">127.0.0.1</prop>
  62. </props>
  63. </property>
  64. </bean>
  65. <bean class="spring.bean.Monster" id="monster01"
  66. p:id="100"
  67. p:name="红孩儿"
  68. p:skill="吐火"
  69. />
  70. <bean class="spring.bean.Monster" id="monster02"
  71. p:id="101"
  72. p:name="红孩儿"
  73. p:skill="吐水"
  74. />

级联简单类型赋值

不会把Date当成简单类型,一般采用ref给Date赋值

级联赋值,Emp需要有get对象方法,因为需要先把dept拿到,顺序不能颠倒

  1. <bean class="spring.bean.Dept" id="dept"/>
  2. <bean class="spring.bean.Emp" id="emp">
  3. <property name="name" value="jack"/>
  4. <property name="dept" ref="dept"/>
  5. <!--级联赋值-->
  6. <property name="dept.name" value="Java开发部门"/>
  7. </bean>

**不使用级联赋值 **

Bean的单例和多例

  1. <!--配置Cat对象
  2. 1. 在默认情况下 scope属性是 singleton
  3. 2. 在ioc容器中, 只要有一个这个bean对象
  4. 3. 当程序员执行getBean时, 返回的的是同一个对象
  5. 4. 如果我们希望每次getBean返回一个新的Bean对象,则可以scope="prototype"
  6. 5. 如果bean的配置是 scope="singleton" lazy-init="true"
  7. 这时,ioc容器就不会提前创建该对象,
  8. 而是当执行getBean方法的时候,才会创建对象(执行构造器)
  9. -->
  10. <bean id="cat" class="spring.bean.Cat" scope="prototype" lazy-init="false">
  11. <property name="id" value="100"/>
  12. <property name="name" value="小花猫"/>
  13. </bean>

细节

Bean的获取方式

1、构造方法

** 在xml配置bean,自动调用无参构造器实例化bean**

2、简单(静态)工厂模式

  1. public class MyStaticFactory {
  2. private static Map<String, Monster> monsterMap;
  3. //使用 static代码块 进行初始化
  4. static {
  5. monsterMap = new HashMap<>();
  6. monsterMap.put("monster01", new Monster(100,"牛魔王","芭蕉扇"));
  7. monsterMap.put("monster02", new Monster(200,"狐狸精","美人计"));
  8. }
  9. //提供一个方法,返回Monster对象
  10. public static Monster getMonster(String key) {
  11. return monsterMap.get(key);
  12. }
  13. }

**会执行类的无参构造器 **

只需要指定工厂类的静态方法(不需要配置工厂类对象)

**需要class路径

  1. 通过静态工厂获取/配置bean
  2. class 是静态工厂类的全路径
  3. factory-method 表示是指定静态工厂类的哪个方法返回对象
  4. constructor-arg value="monster02" value是指定要返回静态工厂的哪个对象**

5.即使有多个bean,静态工厂获取的对象都是同一个

  1. <bean id="monster01"
  2. class="spring.factory.MyStaticFactory"
  3. factory-method="getMonster">
  4. <constructor-arg value="monster01"/>
  5. </bean>
  6. <bean id="monster02"
  7. class="spring.factory.MyStaticFactory"
  8. factory-method="getMonster">
  9. <constructor-arg value="monster02"/>
  10. </bean>
  1. ApplicationContext context = new ClassPathXmlApplicationContext("spr.xml");
  2. Monster monster01 = (Monster) context.getBean("monster01");
  3. System.out.println(monster01.getName() + " 的技能是: " + monster01.getSkill());
  4. Monster monster02 = (Monster) context.getBean("monster02");
  5. System.out.println(monster02.getName() + " 的技能是: " + monster02.getSkill());

3、factory-bean(工厂方法模式)

  1. public class MyInstanceFactory {
  2. private Map<String, Monster> monster_map;
  3. //通过普通代码块进行初始化
  4. {
  5. monster_map = new HashMap<>();
  6. monster_map.put("monster03", new Monster(300, "牛魔王~", "芭蕉扇~"));
  7. monster_map.put("monster04", new Monster(400, "狐狸精~", "美人计~"));
  8. }
  9. //写一个方法返回Monster对象
  10. public Monster getMonster(String key) {
  11. return monster_map.get(key);
  12. }
  13. }

返回的方法不是静态方法,需要告诉spring框架,调用哪个对象的哪个方法获取bean

需要配置工厂类对象

不需要calss路径

1. factory-bean 指定使用哪个实例工厂对象返回bean
2. factory-method 指定使用实例工厂对象的哪个方法返回bean
3. constructor-arg value="monster03" 指定获取到实例工厂中的哪个monster

  1. <bean class="spring.factory.MyInstanceFactory" id="myInstanceFactory"/>
  2. <bean class="spring.factory.MyInstanceFactory" id="myInstanceFactory2"/>
  3. <bean id="my_monster02" factory-bean="myInstanceFactory" factory-method="getMonster">
  4. <constructor-arg value="monster03"/>
  5. </bean>
  6. <bean id="my_monster03" factory-bean="myInstanceFactory2" factory-method="getMonster">
  7. <constructor-arg value="monster03"/>
  8. </bean>

使用同一个容器,调用my_monster02,都是用的同一个实例工厂对象
(factory-bean="myInstanceFactory"),只要它不变化,构建的就是同一个对象
可以有多个实例工厂,那么即使值一样,但不是同一个对象

  1. ApplicationContext ioc =
  2. new ClassPathXmlApplicationContext("beans.xml");
  3. Monster monster02 = ioc.getBean("my_monster02", Monster.class);
  4. Monster monster03 = ioc.getBean("my_monster02", Monster.class);
  5. System.out.println(monster02 == monster03); //true
  6. Monster monster3 = ioc.getBean("my_monster03", Monster.class);
  7. //monster03 和 monster3返回的值都是 monster03

4、FactoryBean接口

实现FactoryBean接口之后,factory-bean、factory-method不需要在配置文件指定
是对第3种方式的简化

  1. public class MyFactoryBean implements FactoryBean<Monster> {
  2. //这个就是你配置时候,指定要获取的对象对应key
  3. private String key;
  4. private Map<String, Monster> monster_map;
  5. { //代码块,完成初始化
  6. monster_map = new HashMap<>();
  7. monster_map.put("monster03", new Monster(300, "牛魔王~", "芭蕉扇~"));
  8. monster_map.put("monster04", new Monster(400, "狐狸精~", "美人计~"));
  9. }
  10. public void setKey(String key) {
  11. this.key = key;
  12. }
  13. @Override
  14. public Monster getObject() throws Exception {
  15. return monster_map.get(key);
  16. }
  17. @Override
  18. public Class<?> getObjectType() {
  19. return Monster.class;
  20. }
  21. @Override
  22. public boolean isSingleton() {//这里指定是否返回单例,默认是true
  23. return false;
  24. }
  25. }

class 指定使用的FactoryBean
key表示就是 MyFactoryBean 属性key
value就是你要获取的对象对应key

  1. <bean id="monster" class="spring.factory.MyFactoryBean">
  2. <property name="key" value="monster04"/>
  3. </bean>
  1. Monster monster = ioc.getBean("monster", Monster.class);

注入Date

只能用于系统时间

实现FactoryBean,解决自定义Date

Bean创建顺序

默认按照配置的顺序创建Bean对象

** 如果将两个bean顺序交换**

先都创建好,再执行Service里的set方法,完成引用

Bean的生命周期---五步

** 创建javaBean对象(House),自己写init方法,desrtoy方法,名字自己定义**

  1. <bean class="spring.bean.House" id="house"
  2. init-method="init"
  3. destroy-method="destroy">
  4. <property name="name" value="北京豪宅"/>
  5. </bean>

**手动关闭才会销毁Bean **

1、Spring容器只对单例的Bean进行完整的生命周期管理

2、如果是多例的Bean,只负责将该Bean初始化完毕,只执行到第4步,使用Bean

配置bean的后置处理器---七步

不指定init-method也会执行,多例对象每次都会执行
在xml中配置后置处理器对象,会作用在该容器创建的所有bean对象

后置处理器, 需要实现 BeanPostProcessor接口

bean初始化方法

对ioc容器中所有的对象进行统一处理
如果类型是House的统一改成上海豪宅

  1. public class MyBeanPostProcessor implements BeanPostProcessor {
  2. @Override
  3. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  4. System.out.println("postProcessBeforeInitialization().. bean="
  5. + bean + " beanName=" + beanName);
  6. //初步体验案例: 如果类型是House的统一改成 上海豪宅
  7. //对多个对象进行处理/编程==>切面编程
  8. if(bean instanceof House) {
  9. ((House)bean).setName("上海豪宅~");
  10. }
  11. return bean;
  12. }
  13. @Override
  14. public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  15. System.out.println("postProcessAfterInitialization().. bean="
  16. + bean + " beanName=" + beanName);
  17. return bean;
  18. }
  19. }
  1. <bean class="com.hspedu.spring.bean.House" id="house"
  2. init-method="init"
  3. destroy-method="destroy">
  4. <property name="name" value="大豪宅"/>
  5. </bean>
  6. <bean class="com.hspedu.spring.bean.House" id="house02"
  7. init-method="init"
  8. destroy-method="destroy">
  9. <property name="name" value="香港豪宅"/>
  10. </bean>
  11. <bean class="spring.bean.MyBeanPostProcessor"
  12. id="myBeanPostProcessor"/>
  1. @Test
  2. public void testBeanPostProcessor() {
  3. ApplicationContext ioc =
  4. new ClassPathXmlApplicationContext("beans02.xml");
  5. House house = ioc.getBean("house", House.class);
  6. System.out.println("使用house=" + house);
  7. House house02 = ioc.getBean("house02", House.class);
  8. System.out.println("使用house02=" + house02);
  9. ((ConfigurableApplicationContext)ioc).close();
  10. }

new对象让Spring管理

循环依赖

丈夫类有妻子字段,妻子类有丈夫字段

singleton+set注入

当两个bean都是多例的时候才会出现异常

singleton+构造注入

无法解决

源码分析

EL表达式

  1. @Data
  2. public class SpELBean {
  3. private String name;
  4. private Monster monster;
  5. private String monsterName;
  6. private String crySound; //叫声
  7. private String bookName;
  8. private Double result;
  9. //cry 方法会返回字符串
  10. public String cry(String sound) {
  11. return "发出 " + sound + "叫声...";
  12. }
  13. //read 返回字符串
  14. public static String read(String bookName) {
  15. return "正在看 " + bookName;
  16. }
  17. }

xml

  1. <!--配置一个monster对象-->
  2. <bean id="monster01" class="spring.bean.Monster">
  3. <property name="monsterId" value="100"/>
  4. <property name="name" value="蜈蚣精~"/>
  5. <property name="skill" value="蜇人~"/>
  6. </bean>
  7. <!-- spring el 表达式使用
  8. 老师解读
  9. 1. 通过spel给bean的属性赋值
  10. -->
  11. <bean id="spELBean" class="spring.bean.SpELBean">
  12. <!-- sp el 给字面量 -->
  13. <property name="name" value="#{'韩顺平教育'}"/>
  14. <!-- sp el 引用其它bean -->
  15. <property name="monster" value="#{monster01}"/>
  16. <!-- sp el 引用其它bean的属性值 -->
  17. <property name="monsterName" value="#{monster01.name}"/>
  18. <!-- sp el 调用普通方法(返回值) 赋值 -->
  19. <property name="crySound" value="#{spELBean.cry('喵喵的..')}"/>
  20. <!-- sp el 调用静态方法(返回值) 赋值 -->
  21. <property name="bookName" value="#{T(com.hspedu.spring.bean.SpELBean).read('天龙八部')}"/>
  22. <!-- sp el 通过运算赋值 -->
  23. <property name="result" value="#{89*1.2}"/>
  24. </bean>
标签: spring

本文转载自: https://blog.csdn.net/qq_65186476/article/details/141334230
版权归原作者 _CYX_ 所有, 如有侵权,请联系我们删除。

“Spring1~~~”的评论:

还没有评论