框架整体
我们看到其中核心部分正好对应我们必须导入的四个核心包Beans/Core/Context/SpEL(必须导的包还有log4j、logging)
IOC
IOC全称inversion Of Control,它是指将对象的创建权力转交给了Spring框架,
- 传统中:比如我们通过在Servlet中自行创建UserService接口下的UserServiceImp类对象完成业务需求,这样虽然借助了JavaWeb三层模型耦合性有所下降,但我们的Service接口或类散落在各个角落,这样维护或替换还是比较繁琐的
- 通过IOC:我们可以由描述(即是xml 或注解)借由SPRING框架去产生或获取特定对象。此时我们的开发人员要做的事情就是提供一些创建这些对象所必需的的一些信息(元数据)。只需要向容器申请要什么,不再负责创造什么。 此时就类似买房过程
通过SpringIOC机制创建对象的方法
- 通过构造器创建
需要先在配置文件xml中以bean标签定义spring容器中的对象元数据
<!-- 1.构造器创建 -->
<bean name="user" class="domain.User"></bean>
接下来直接按name向容器索要对象即可,由于bean对象属性scope默认singleton单例所以获取两次都是同一个对象。
@Test
public void test01() {
// 1.开启spring容器 - 加载配置文件
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("a_hello/applicationContext.xml");
// 2.索要对象
User user = (User) ac.getBean("user");
User user1 = (User) ac.getBean("user");
System.out.println(user == user1);
ac.close();
}
- 通过工厂静态方法创建
先要有一个工厂
public class Factory {
// 提供一个静态方法,获得对象
public static User getUser() {
System.out.println("static Factory");
return new User();
}
}
然后再到spring容器中定义user1对象的创建方式为通过Factory这个工厂的getUser方法创建
<bean name="user1" class="b_create.Factory" factory-method="getUser" ></bean>
- 通过工厂普通方法创建
public class Factory {
// 提供普通方法
public User newUser() {
System.out.println("Factory method");
return new User();
}
}
xml中由于这是普通方法,所以还是先得有factory对象才能执行newUser方法
<!-- 3.工厂方法方式:工厂类中提供普通方法 -->
<!-- 创建factory对象 -->
<bean name="factory" class="b_create.Factory"></bean>
<bean name="user2" factory-method="newUser" factory-bean="factory"></bean>
DI——依赖注入的方式(4种)
- Set方法注入(要求必定实现set方法)
其中value是注入基本类型(基本数据类型+String类型)ref则注入引用类型
<bean name="user" class="domain.User">
<!-- property属性
|- name: 属性名
|- value: 基本类型 值
|- ref: 注入的对象name
-->
<property name="name" value="lucy"></property>
<property name="age" value="19"></property>
<property name="car" ref="car1"></property>
</bean>
<bean name="car1" class="domain.Car" >
<property name="name" value="兰博基尼"></property>
<property name="color" value="黄色"></property>
</bean>
- 构造器注入
注意type应该是完整类名(java.lang可以省略) index用于区别有多个类型列表一样的构造器
<bean name="user1" class="domain.User">
<!-- 构造器参数:
|— type:参数类型 - 完整类型
|- value:普通类型值
|- ref:引用类型值 对象name
|- index:参数的索引
-->
<constructor-arg type="String" value="tom" index="1" ></constructor-arg>
<constructor-arg type="Integer" value="20"></constructor-arg>
</bean>
- p命名空间注入
<bean name="user2" class="domain.User"
p:age="23" p:name="jack" p:car-ref="car1">
</bean>
- spel表达式注入
<bean name="user3" class="domain.User">
<property name="name" value="#{user1.name}"></property>
<property name="age" value="#{user.age}"></property>
</bean>
集合类型属性的注入
- list类型
<property name="list">
<list>
<value>haha</value>
<value>haha</value>
<value>haha</value>
<!-- <ref bean=""/> -->
</list>
</property>
- 普通数组
<property name="arr">
<array>
<value>lucy</value>
<value>tom</value>
</array>
</property>
- Map类型
<property name="map">
<map>
<entry key="user1" value-ref="user"></entry>
</map>
</property>
- properties类型
<property name="pros">
<props>
<prop key="driver">com.mysql.jdbc.Driver</prop>
</props>
</property>
注解代替xml配置
如何使用注解:
-
导入spring-aop-.RELEASE.jar的包
-
添加context命名空间 <context:component-scan base-package="">
该命名空间表示:会对该base-package下的类的注解进行扫描 -
@Component(“name”)类似bean标签在容器中定义对象
- Repository(“name”)
- Service(“name”)
- Controller(“name”)
-
@Value(“xxx”)
可以添加属性或者set方法上对某个属性直接注入或者借由某个set方法注入xxx -
@AutoWired 自动装配注入
@Resource(name="")通过name指定注入某种引用对象 -
@Scope(scopeName=“singleton”) 创建策略,默认还是单例
-
@PostConstrut 相当于init-method
-
@PreDestroy 相当于destroy-method
Spring+JUnit
-
@RunWith(SpringJUnit4ClassRunner.class)
他将指定jUnit与Spring容易一同运行 -
@ContextConfiguration(locations = “classpath:e_junit/applicationContext.xml”)
他将指定将采用哪个xml的规范来创建对象
// 将junit和 spring 容器进行整合
@RunWith(SpringJUnit4ClassRunner.class)
// 指定容器对应的配置文件
@ContextConfiguration(locations = "classpath:e_junit/applicationContext.xml")
public class UserDaoTest {
@Autowired//@Resource("userDaoImpl")
UserDao ud;
@Autowired
User u;
@Test
public void test01() {
User user = ud.getUser();
System.out.println(user);
System.out.println(u);
}
}
- Repository ——Component的一种,一般用来定义Dao层实例
@Repository
public class UserDaoImpl implements UserDao {
@Override
public User getUser() {
// 模拟方法
System.out.println("UserDao getUser");
return new User("rose", 23);
}
}
我们看到,这样在Test方法里面并没有声明ClassPathXmlApplicationContext对象,但却还是完成了通过Spring容器创建UserDaoImpl对象