ioc容器
三种配置方式
XML:最基本,最完整、强大
注解(Annotation),@Sine 2.5
- 疑问:基于注解,怎么读取
<context:component-scan base-package="com.xxx"/>并去扫描,初始化有此类的bean? 会用到自定义空间解析 - 常用几种注解
- @Componet 通用型
- @Controller controller层
- @Service service层
- @Repository dao层
- @Autowired 默认byType注入
- @Resource JSR,默认byName注入
- 疑问:基于注解,怎么读取
Java配置, @Sine 3.0
理解:
基于XML功能强大,但是与代码分开了,感觉编写起来麻烦,基于注解和Java配置,让配置像写代码一样,易于理解和维护,但是可能缺失了部分功能.无论使用哪种方式,最终达到的效果是一样的,即会统一转化为Spring BeanDefinition等配置。
依赖注入
自定义属性解析器
定义bean
package com.desmond.springlearning.customproperty; import java.util.Date; /** * @author presleyli * @date 2018/9/11 下午10:04 */ public class UserBean { private Date birthday; public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } }定义解析器
package com.desmond.springlearning.customproperty; import java.beans.PropertyEditorSupport; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Locale; /** * @author presleyli * @date 2018/9/11 下午10:04 */ public class DatePropertyEditor extends PropertyEditorSupport{ @Override public void setAsText(String text) throws IllegalArgumentException { try { DateFormat df = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA); this.setValue(df.parse(text)); } catch (ParseException e) { e.printStackTrace(); } } }配置文件
<?xml version="1.0" encoding="UTF-8"?> <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="default"> <bean id="userBean" class="com.desmond.springlearning.customproperty.UserBean"> <!-- 时间属性,需要属性编辑器 --> <property name="birthday" value="2017-11-26"/> </bean> <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer"> <property name="customEditors"> <map> <entry key="java.util.Date" value="com.desmond.springlearning.customproperty.DatePropertyEditor"/> </map> </property> </bean> </beans>测试
package com.desmond.springlearning.customproperty; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author presleyli * @date 2018/9/11 下午10:11 */ public class Test { public static void main(String[] args) { BeanFactory factory = new ClassPathXmlApplicationContext("customproperty/applicationContext.xml"); UserBean ub = factory.getBean(UserBean.class); System.out.println(ub.getBirthday()); } }输出
Sun Nov 26 00:00:00 CST 2017大概原理:
Spring 会内置一些字面量的解析器,比如把字符串"2"转化成整数2. 也会根据用户的需求,填充自定义属性,过程如下
循环依赖(构造器)
描述
A 依赖 B, B 也依赖 A:
public Class Bar {
private Foo foo;
public Bar(Foo foo) {
this.foo = foo;
}
// setter and getter
}
public Class Foo {
private Bar bar;
public Foo(Bar bar) {
this.bar = bar;
}
// setter and getter
}
运行时,抛出BeanCurrentlyInCreationException.
解决
容器创建A(提早曝光,这时只是 A a = new A(), a只是最原始的实例,没有装配任何属性) -> 发现需要依赖B -> new B(a) -> 发现需要实例a, 因为 a 已经提早曝光了,所以能够拿到这个最原始的实例,完成B的实例 b的创建(是先new B(),然后setA,还是直接 new B(a)?) -> 返回实例 b -> a.setB(b) -> 结束.
重写Bean定义
两种重写机制:配置元素 和 容器级别
配置元素
利用配置元素的先后顺序,相同的bean name, 后面的会覆盖前面的
基于Java配置
两个配置类(同一配置类里,bean name唯一)
package com.desmond.springlearning.bean_name_override; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; /** * @author presleyli * @date 2018/9/13 上午4:18 */ @Data @NoArgsConstructor @AllArgsConstructor public class Foo { private String name; }package com.desmond.springlearning.bean_name_override; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @author presleyli * @date 2018/9/13 上午4:18 */ @Configuration public class ConfigurationBean1 { @Bean public Foo foo1() { return new Foo("foo1 from b1"); } @Bean public Foo foo2() { return new Foo("foo2 from b1"); }package com.desmond.springlearning.bean_name_override; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @author presleyli * @date 2018/9/13 上午4:18 */ @Configuration public class ConfigurationBean2 { @Bean public Foo foo1() { return new Foo("foo1 from b2"); } @Bean public Foo foo2() { return new Foo("foo2 from b2"); } }- 测试类
package com.desmond.springlearning.bean_name_override; import org.springframework.context.annotation.AnnotationConfigApplicationContext; /** * @author presleyli * @date 2018/9/13 上午4:20 */ public class Test { public static void main(String[] args) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ConfigurationBean1.class, ConfigurationBean2.class); Foo foo = applicationContext.getBean("foo1", Foo.class); System.out.println(foo.getName()); } }- 结果
foo1 from b2
基于XML配置
连个配置文件(同一配置文件,beanName唯一)
<?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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd " default-autowire="default"> <bean id="foo" class="com.desmond.springlearning.bean_name_override.Foo" p:name="I'm foo from config1."/> </beans><?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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd " default-autowire="default"> <bean id="foo" name="foo2" class="com.desmond.springlearning.bean_name_override.Foo" p:name="I'm foo from config2."/> </beans>测试类
package com.desmond.springlearning.bean_name_override; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author presleyli * @date 2018/9/13 上午4:20 */ public class Test2 { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext(new String[]{ "bean_name_override/applicationContext2.xml", "bean_name_override/applicationContext1.xml" }); Foo foo = applicationContext.getBean("foo", Foo.class); System.out.println(foo.getName()); } }结果
I'm foo from config1.
容器级别
不同的容器,可以存在同名的bean, 比如child container与parent container.
1万+



被折叠的 条评论
为什么被折叠?



