1、DI 依赖注入
1.1 构造器注入
上文已经提到过,此处不再赘述!
1.2 Set方式注入
- 依赖注入:Set注入!
- 依赖: bean对象的创建依赖于容器
- 注入:bean对象中的所有属性,由容器来注入!
【环境搭建】
-
复杂类型
public class Address { private String address; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "Address{" + "address='" + address + '\'' + '}'; } }
-
真实测试对象
public class Student { private String name; private Address address; private String[] books; private List<String> hobbies; private Map<String,String> card; private Set<String> cources; private String work; private Properties info; //以下省略了一系列的Getter、Setter //toString()方法 }
-
beans.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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="student" class="com.demut.pojo.Student"> <property name="name" value="Demut"/> </bean> </beans>
-
MyTest.java
public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Student student = (Student) context.getBean("student"); System.out.println(student.getAddress()); } }
【使用容器注入信息】
beans.xml
文件:
<bean id="address" class="com.demut.pojo.Address">
<property name="address" value="南京"/>
</bean>
<bean id="student" class="com.demut.pojo.Student">
<!--第一种: 普通值注入,value-->
<property name="name" value="李华"/>
<!--第二种: Bean注入, ref-->
<property name="address" ref="address"/>
<!--数组注入, ref-->
<property name="books">
<array>
<value>红楼梦</value>
<value>西游记</value>
<value>水浒传</value>
<value>三国演义</value>
</array>
</property>
<!--list-->
<property name="hobbies">
<list>
<value>摄影</value>
<value>编程</value>
<value>网球</value>
</list>
</property>
<!--Map-->
<property name="card">
<map>
<entry key="身份证号" value="123123123456781011"/>
<entry key="银行卡号" value="213243567823435467"/>
</map>
</property>
<!--Set-->
<property name="cources">
<set>
<value>数学分析</value>
<value>高等代数</value>
<value>解析几何</value>
</set>
</property>
<!--null值注入-->
<property name="work">
<null/>
</property>
<!--Properties-->
<property name="info">
<props>
<prop key="学号">123456</prop>
<prop key="姓名">李华</prop>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</props>
</property>
</bean>
1.3 拓展方式注入
也可以使用p-命名空间
和c-命名空间
注入!
- p-命名空间,更像简化版的Set注入,要求必须有无参构造,否则会报错!
- c-命名空间,使用了有参构造器进行了注入,要求必须有有参构造,否则会报错!
使用前提:(引入相应的依赖)
<!--p依赖-->
xmlns:p="http://www.springframework.org/schema/p"
<!--c依赖--> xmlns:c="http://www.springframework.org/schema/c"
使用测试:
userbeans.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:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--p命名空间注入, 相当于通过Set注入,要求必须有无参构造-->
<bean id="user" class="com.demut.pojo.User" p:name="Demut" p:age="20"/>
<!--c命名空间注入, 相当于通过有参构造器注入-->
<bean id="user2" class="com.demut.pojo.User" c:name="李华" c:age="19"/>
</beans>
测试类:
@Test
public void test() {
ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");
User user1 = context.getBean("user1", User.class);
User user2 = context.getBean("user2", User.class);
System.out.println(user1);
System.out.println(user2);
}
1.4 Bean的作用域
-
单例模式(Spring的默认机制,只有一个对象被生成,getBean到的永远是同一个对象)
<bean id="user2" class="com.demut.pojo.User" c:age="18" c:name="Demut" scope="singleton"/>
-
原型模式:每次从容器中get的时候,都会产生一个新对象!
<bean id="user2" class="com.demut.pojo.User" c:age="18" c:name="Demut" scope="prototype"/>
@Test public void test() { ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml"); User user = context.getBean("user2", User.class); User user2 = context.getBean("user2", User.class); System.out.println(user==user2); }
-
其余的request、session、application这些还能在web开发中使用到!
2、Bean的自动装配
- 自动装配是Spring满足bean依赖的一种方式!
- Spring会在上下文中自动寻找,并自动给bean装配属性!
在Spring中有三种装配的方式:
- 在xml中显示的配置
- 在java中显示配置
- 隐式的自动装配bean【重要】
2.1 测试
环境搭建: 一个人,有两个宠物(狗、猫)。
ByName自动装配
<!--自动装配:
byName: 会自动在容器上下文中查找,和自己对象set方法后面的值对应的bean-id!
-->
<bean id="person" class="com.demut.pojo.Person" autowire="byName">
<property name="name" value="Demut"/>
</bean>
ByType自动装配
<!--自动装配:
byType: 会自动在容器上下文中查找,和自己对象属性类型相同的bean!
-->
<bean id="person" class="com.demut.pojo.Person" autowire="byType">
<property name="name" value="Demut"/>
</bean>
小结:
- byName: 需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性的set方法的值一致!
- byType:需要保证所有bean的class唯一,并且这个bean需要和自动注入的属性的类型一致!
2.2 使用注解实现自动装配
jdk1.5开始支持注解,Spring2.5已经支持注解了
要使用注解须知:
-
导入约束:context约束
-
配置注解的支持: <context:annotation-config/>
<?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.xsd"> <!--开启注解支持--> <context:annotation-config/> </beans>
@Autowired
直接在属性上使用即可!Autowired默认按照bean的类型进行装配。
使用Autowired之后可以不用编写Set方法,前提是这个自动装配的属性在IOC(Spring)容器存在,且符合名字byname!
public class Person {
@Autowired
private Cat cat;
@Autowired
private Dog dog;
private String name;
}
如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解【@Autowired】完成的时候,我们可以使用@Qualifier(value=“xxx”)去配置@Autowired的使用,指定一个唯一的bean对象注入!
@Resource
public class Person {
@Resource(name = "cat2")
private Cat cat;
@Resource
private Dog dog;
}
小结:@Resource和@Autowired的区别:
- 都是用来自动装配的,都可以放在属性字段上
- @Autowired默认通过byType的方式实现,而且必须要求这个对象存在!【常用】
- @Resource默认通过byName的方式实现,如果找不到名字,则通过byType实现!如果两个都找不到,则报错!【常用】
- 执行顺序不同:@Autowired优先byType,@Resource优先byName
写在最后
Everything ought to be beautiful in a human being: face,dress,soul and idea.