Spring学习日志(1)
Spring框架的IOC开发的两种模式,包括XML开发与注解开发的比较
Spring的简介
什么是Spring
Spring是一个开源框架,于2003年兴起的轻量级java开发框架,简单而言,Spring是一个分层的JAVASE/EEfull-stack(一站式)开源框架
Spring入门(IOC)
一、什么是IOC
- IOC(Inversion of Control):控制反转。
控制反转:将对象的控制权反转交给Spring
- 导包 (官网:http://SPring.io/)
- 引入约束文件
在spring的解压路径下spring-framework-4.2.4.RELEASE\docs\spring-framework-reference\html\xsd-configuration.html
<?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">
</beans>
- Spring底层实现原理:
- Spring学习路线
- 把类交给Spring处理,有两种方式
1 . 通过XML配置方式
package Spring.demo1;
/**
* 业务管理层的接口
* @author rong
*
*/
public interface UserService {
public void add();
}
package Spring.demo1;
/**
* 业务管理层的实现类
* @author rong
*
*/
public class UserServiceImp implements UserService {
private String name;
public void setName(String name) {
this.name = name;
}
@Override
public void add() {
// TODO Auto-generated method stub
System.out.println("UserServiceImp被执行了"+name);
}
}
package Spring.demo1;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class Test {
@org.junit.Test
public void demo1(){
// UserService user=new UserServiceImp();
UserServiceImp user=new UserServiceImp();
user.setName("张三");
user.add();
}
/**
* Spring 方式的调用
*/
@org.junit.Test
public void demo2(){
/**
* 创建Spring工厂
*/
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("application.xml");
UserService User = (UserService) applicationContext.getBean("UserService");
User.add();
}
@org.junit.Test
public void demo3(){
/**
* 加载磁盘上的配置文件
*/
ApplicationContext applicationContext=new FileSystemXmlApplicationContext("D:\\111\\application.xml");
UserService user = (UserService) applicationContext.getBean("UserService");
user.add();
}
}
XML配置文件
其中包括了属性的注入(通过构造函数或Set方法)
SPEL的/font>的注入
集合的注入的注入
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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">
<!-- Spring 入门的配置
id 相当于Spring生成类时,该类的一个编号,,,用于getBean()
name 作用与上面相同
class 生成类的地址 包名.类名
init-method Spring在初始化该类的时候所执行的方法
destory-method Spring在关闭工厂的时候所执行的方法
scope 所创建的类是 单例模式-无论getBean几次,都只new一次(singleton)
多例模式-getBean几次就new几次 (prototype)
request 生成的对象存放在域中
session 同上
globalsession 作用见word
factory-method 在类初始化时,若不写默认调用无参的构造方法,若想指定构造方法,则使用该方法
-->
<bean id="UserService" class="Spring.demo1.UserServiceImp" >
<property name="name" value="张三"></property>
</bean>
<bean id="Custom" class="Spring.demo2.CustomImp" init-method="init" destroy-method="destroy" scope="prototype" >
</bean>
<bean id="person" class="Spring.demo3.person" >
</bean>
<!--
属性的注入
有两种方式
1.通过构造方式(有参构造) <constructor-arg name="name" value="奔驰"></constructor-arg>
2.通过类的set方法 <property name="price" value="1212.0"></property>
注意:
当成员不在是简单的属性,而实某一个对象时,value变为ref
-->
<bean id="car1" class="Spring.demo4.car1">
<constructor-arg name="name" value="奔驰"></constructor-arg>
<constructor-arg name="price" value="12220.0"></constructor-arg>
</bean>
<!-- <bean id="car2" class="Spring.demo4.car2">
<property name="name" value="东风"></property>
<property name="price" value="1212.0"></property>
</bean > -->
<!-- 改用P名称空间注入 -->
<bean id="car2" class="Spring.demo4.car2" p:name="东风" p:price="4212.0" >
</bean>
<!-- <bean id="staff" class="Spring.demo4.staff">
<constructor-arg name="name" value="张三"></constructor-arg>
<constructor-arg name="car" ref="car1"></constructor-arg>
</bean> -->
<!--
改用P名称 空间注入
注意:
P名称空间注入走的也是set方法, 官方目的是简化set注入的property标签的写法
有set方法就不要有 有参的构造方法
-->
<!-- <bean id="staff" class="Spring.demo4.staff" p:name="张三" p:car-ref="car1">
</bean> -->
<!--
SPEL注入
使用#{}作为定界符
就是给改变了 value的赋值
没有改变的是 property
可以为数、字符串、boolean、其他对象、其他对象的属性和方法、支持运算符
-->
<!-- <bean id="staff" class="Spring.demo4.staff">
<property name="name" value="#{'张三'}"></property>
<property name="car" value="#{car1}"></property>
</bean> -->
<!-- 调用其他类的方法 -->
<bean id="calculate" class="Spring.demo4.calculate"></bean>
<bean id="staff" class="Spring.demo4.staff">
<property name="name" value="#{calculate.name}"></property>
<property name="car" value="#{car1}"></property>
</bean>
<!-- 集合属性的注入======================一般用于不同的框架的整合= -->
<bean id="collectionBean" class="Spring.demo5.collectionBean">
<!-- int数组的注入 -->
<property name="arr">
<list>
<value>1</value>
<value>2</value>
<value>3</value>
</list>
</property>
<!-- List<String>集合注入 -->
<property name="list">
<list>
<value>张三</value>
<value>李四</value>
<value>王五</value>
</list>
</property>
<!-- Set<String>set集合注入 -->
<property name="set">
<set>
<value>张三</value>
<value>李四</value>
<value>王五</value>
</set>
</property>
<!-- map<int,String>集合的注入 -->
<property name="map">
<map>
<entry key="1" value="张三"></entry>
<entry key="2" value="李四"></entry>
<entry key="3" value="王五"></entry>
</map>
</property>
</bean>
</beans>
2 . 通过注解方式
- 导包
除了引入基本的开发包,还需要引入AOP包 - 引入约束文件
哪里找?
spring-framework-4.2.4.RELEASE-docs\spring-framework-reference\html中找xsd-configuration.html中找到Context约束(其中包含了beans约束,beans约束是Spring中最基本的约束) - 开启组件扫描(在XML文件中)
<!--=====扫描是为了扫描类上的注解 ============-->
<context:component-scan base-package="demo1,demo2"></context:component-scan>
编写测试类
package demo1;
public interface UserDao {
public void sava();
}
package demo1;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component(value="UserDaoImp")//相当于<bean id="UserDaoImp" class="demo1.UserDaoImp"></bean>
public class UserDaoImp implements UserDao {
@Value("张三")
private String name;
//可以不提供set方法,则需要将属性的注解添加到属性上;若有set方法,则需要将属性的注入添加到set方法上
/*@Value("张三")
public void setName(String name) {
this.name = name;
}
*/
@Override
public void sava() {
// TODO Auto-generated method stub
System.out.println("sava()方法执行了。。");
}
@Override
public String toString() {
return "UserDaoImp [name=" + name + "]";
}
}
说明:属性注入的注解分为以下类型
- 普通类型
@value(“”)设置普通属性的值 - 对象类型
@Autowired:设置对象的属性的值。
注意:按照类型完成属性注入,而不是名称,与Component(“CLassName”)无关
一般我们习惯按名称匹配
下面两个同时写
@Autowired
@Qualifier(value=”ClassName”) //强制使它按照名称的属性注入
@Resource(name=”ClassName”):完成对象属性的注入,等价于上面连续两个(开发中常用)
Bean的其他注解
package demo2;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component(value="custom")//<bean id="custom" class="demo2" init-method="init" destory-method="destory"></bean>
@Scope("prototype")
public class custom {
@PostConstruct//初始化注解,相当于nit-method="init"
public void init(){
System.out.println("初始化方法执行了");
}
public void save(){
System.out.println("save方法执行了");
}
@PreDestroy//destory注解,相当于destory-method="destory"
public void destory(){
System.out.println("destory方法执行了");
}
}
说明:
- 生命周期相关的注解
<bean id="custom" class="demo2" init-method="init" destory-method="destory"></bean>
@PostConstruct:初始化方法
@PreDestory:销毁方法
2. Bean的作用范围注解(重要)
@Scope( “ ”) :作用范围
- Prototype : 多例
- Request :
- Session:
- Globalsession:
测试案例:
package demo2;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
@org.junit.Test
public void test1(){
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
custom c = (custom) applicationContext.getBean("custom");
System.out.println(c);
custom c2 = (custom) applicationContext.getBean("custom");
System.out.println(c2);
}
}
输出结果:
初始化方法执行了
[email protected]
初始化方法执行了
[email protected]
说明:由于使用了@Scope(“prototype”),多例模式初始化了两次,得到两个不同的id;
3 . 两种方式的比较
- 适用场景
- XML:可以使用任何场景
- 结构清晰,维护方便
- 注解:必须修改源代码(如果你无法修改源代码,只能用XML)
- 开发方便,速度快
- XML:可以使用任何场景
4 . XML与注解的整合开发
思路:用XML用来管理类的注入,用注解完成属性的注入。
测试案例:
package Demo3;
import org.springframework.stereotype.Component;
//@Component("order")
public class order {
public void play()
{
System.out.println("生产产品");
}
}
package Demo3;
import javax.annotation.Resource;
import org.springframework.stereotype.Component;
//@Component("orderService")//相当于<bean id="orderService" class="Demo3.orderService"></bean>
public class orderService {
@Resource(name="order")//这个name就是配置文件(applicationContext.xml)里面的或者
//如果是用的类上注解等同于@Component(value=”id/name”)中的id
private order od;
public orderService() {
System.out.println("无参构造方法被调用...");
// TODO Auto-generated constructor stub
}
public void t(){
od.play();
}
}
package Demo3;
import javax.annotation.Resource;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Test {
@Resource(name="orderService")
private orderService se;
@org.junit.Test
public void test1(){
se.t();
}
}
配置文件
<?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
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--=====扫描是为了扫描类上的注解 ============-->
<!-- context:component-scan base-package="demo1,demo2"></context:component-scan-->
<context:annotation-config/>
<!-- =======在没有扫描的情况下,使用注解 @Resource @value、@Autowired、@Qulifier -->
<bean id="peopleImp" class="Demo1.peopleImp"></bean>
<bean id="order" class="Demo3.order"></bean>
<bean id="orderService" class="Demo3.orderService"></bean>
</beans>