上面一节我们说了spring的体系和jar包的依赖关系,这节笔者主要详解一下spring3.x
根据第一节。添加这4个jar包以及它的依赖包(spring-Context其实还依赖了aop但是这里因为讲解IOC所以不用依赖也是可以的)。所以上图为他们的4个jar包名称。
(下面搭建项目时在讲解)
概述部分讲解完毕。下面开始spring的核心之一IOC部分
注意:这里需要理解什么是注入。(举例,比如普通的set方法就是一种注入等等。)
注意:现在xml文件用什么名字无所谓。
比如:写好了dao层之后:
配置依赖注入:service与dao层之间的关系:
在service层中写一个register方法,调用dao层的方法(注入的dao中有save方法)如下:
package springIoc.service;
import springIoc.dao.XXDao1;
public class XXService1 {
private XXDao1 xxDao1;
public void setXxDao1(XXDao1 xxDao1) {
this.xxDao1 = xxDao1;
}
public void rgeister(){
xxDao1.save();
}
}
初始化和资源的获取测试:
package springIoc.test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import springIoc.service.XXService1;
public class Client {
public static void main(String[] args) {
/* 注意这是直接new对象获取,耦合度很高,没有调用spring来管理的bean == 不采用
* XXService1 xxService1 = new XXService1();
xxService1.rgeister();
*/
//Spring容器的初始化
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("springIoc/bean.xml");
//获取资源
//XXDao1 xxdao1 = (XXDao1) ac.getBean("xxDao1");
//xxdao1.save();
XXService1 xxService1 = (XXService1) ac.getBean("xxService1");
xxService1.rgeister();
}
}
结果成功!
特别注意:以上主要ioc已经讲解完毕!下面的Ioc配置部分很重要,两种方式在实际开发中用到的都很多!
a、调用默认的构造方法 (推荐)
b、静态工厂方法初始化:老系统才有可能用到(现在已经完全不用了)
* scope属性的取值:
* singleton :默认值.单例的.Spring生成Bean的时候采用的是单例的模式.
* prototype :多例的.Spring生成Bean的时候采用的是多例的模式.每次getBean的时候都会得到一个新的Bean的实例.(与Struts2整合时要使用此值)
* request :应用在web应用中.创建一个Bean的实例将Bean实例存入到request域中.
* session :应用在web应用中.创建一个Bean的实例将Bean的实例存入session域中.
* globalsession :应用在web应用中.全局session.一般用于Porlet应用环境.如果没有Porlet环境.配置全局session等价于session.
拓展:
Bean的完整的生命周期:
Spring框架管理Bean的时候,非常精确.Bean的生成过程中有11个步骤.11个步骤才构成了Bean的完整的生命周期.
1.instantiate bean对象实例化
2.populate properties 封装属性
3.如果Bean实现BeanNameAware 执行 setBeanName
4.如果Bean实现BeanFactoryAware 或者 ApplicationContextAware 设置工厂 setBeanFactory 或者上下文对象 setApplicationContext
5.如果存在类实现 BeanPostProcessor(后处理Bean) ,执行postProcessBeforeInitialization
6.如果Bean实现InitializingBean 执行 afterPropertiesSet
7.调用 指定初始化方法 init
8.如果存在类实现 BeanPostProcessor(处理Bean) ,执行postProcessAfterInitialization
9.执行业务处理
10.如果Bean实现 DisposableBean 执行 destroy
11.调用 指定销毁方法 customerDestroy
* 第三步和第四部为了让Bean了解Spring的环境的..
* 第五步和第八部是实现了一个接口BeanPostProcessor.
注意:当非单例时,初始化方法正常执行,但是销毁方法就不会执行了。
a、构造器注入(调用默认构造方法):通过传参数
0 先定义一个bean类,只提供有参的构造方法(并给每个参数提供get方法,方便测试时判断是否注入进去值)
package springIoc.bean;
import java.util.Date;
public class Bean1 {
private String name;
private int age;
private Date birthday;
//提供了有参构造方法,没有提供默认的构造方法
public Bean1(String name, int age, Date birthday) {
super();
this.name = name;
this.age = age;
this.birthday = birthday;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public Date getBirthday() {
return birthday;
}
}
1、编写bean.xml交给spring管理这个类。
2.编写测试类,判断是否注入成功
package springIoc.test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import springIoc.bean.Bean1;
public class Client {
public static void main(String[] args) {
//Spring容器的初始化
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("springIoc/bean.xml");
//获取资源
Bean1 bean1 = (Bean1) ac.getBean("bean1");
System.out.println("姓名:"+bean1.getName()+"年龄:"+bean1.getAge()+"现在时间:"+bean1.getBirthday());
}
}
打印出:姓名:小马同志年龄:26现在时间:Fri Oct 27 09:47:20 CST 2017
0 先定义一个bean类,定义的字段需要提供setter方法(不然注入不进去)并提供默认的构造方法(必须)
package springIoc.bean;
import java.util.Date;
public class Bean1 {
private String name;
private int age;
private Date birthday;
public Bean1() {
super();
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public Date getBirthday() {
return birthday;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
1、编写bean.xml交给spring管理这个类。
2.编写测试类
package springIoc.test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import springIoc.bean.Bean1;
public class Client {
public static void main(String[] args) {
//Spring容器的初始化
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("springIoc/bean.xml");
//获取资源
Bean1 bean1 = (Bean1) ac.getBean("bean1");
System.out.println("姓名:"+bean1.getName()+"年龄:"+bean1.getAge()+"现在时间:"+bean1.getBirthday());
}
}
测试成功。
e、注入集合数据
两种形式:
* 加载配置文件的时候一并引入.
* ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"applicationContext.xml", "applicationContext2.xml");
* 总的配置文件中引入其他的配置文件.
*
基于xml的配置文件就讲解到这。需要会。下面说一下基于注解的配置也是同样重要,
b、指定要扫描的包
c、在Bean上面加入@Component注解
0、配置a和b的步骤
1 之后执行c在指定的类中添加注解(control层和service层以及dao层都需要添加各自的注解)(稍后会有详细的注解介绍)
package springIoc.dao;
import org.springframework.stereotype.Component;
/**
* @Component是spring的一个注解,它是把XXDao1看做一个组件。
* 就相当于xml中
* @author mch
*
*/
@Component
public class XXDao1 {
public void save() {
System.out.println("SPRING3.XIOC成功了");
}
}
注意:@Component(value="xxDao1") 也可以写成这种注解而value值相当于bean的id
2、编写测试类运行结果
package springIoc.test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import springIoc.dao.XXDao1;
public class Client {
public static void main(String[] args) {
//Spring容器的初始化
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("springIoc/springxml.xml");
//获取资源
XXDao1 xxDao1 = (XXDao1) ac.getBean("xxDao1");
xxDao1.save();
}
}
b、@Component的衍生注解@Controller @Service @Repository
作用:和@Component作用一样,让Spring容器管理(实例化)当前的bean。
属性: value:指定bean的名称。默认值是当前类的简单类名首字母小写
特点:在三成架构中,每个注解对应一层,使语义更加明确。
@Controller:一般用在表现层,比如struts2的action上
@Service:一般用在业务层,比如Service实现
@Repository:一般用在持久层,比如Dao实现
c、@Autowired
作用:自动按类型注入需要的对象。当使用了该注解时,setter就不是必须的了。
属性:
required:是否必须注入成功。默认值是true。
true:必须注入成功,如果出现注入失败,抛出异常。
false:不一定注入成功,不抛异常。
注意事项:
一个Service接口:IBookService
两个Service实现:BookServiceImpl1 BookServiceImpl2
由于@Autowired是自动按类型注入,当使用接口类型时,就看变量的名称,如果变量名称是bookServiceImpl1,则使用BookServiceImp1这个实现类,
如果变量名是bookServiceImpl2,则使用BookServiceImpl2这个实现类。如果没有符合规范的名称(类名首字母小写),则报错。
到底注入哪个实现类:
@Autowried
private BookService bookServiceImpl1;//注入BookServiceImpl1
@Autowried
private BookService bookServiceImpl2;//注入BookServiceImpl2
@Autowried
private BookService bookService;//注入失败
d、@Value
作用:注入基本类型和String。
属性:value:SpEL表达式,要注入的值
package springIoc.dao;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* @Component是spring的一个注解,它是把XXDao1看做一个组件。
* 就相当于xml中
* @author mch
*
*/
@Component(value="xxDao1")
public class XXDao1 {
@Value("小码")
private String name;
public void save() {
System.out.println("SPRING3.XIOC成功了");
}
public String getName() {
return name;
}
}
提供get方法查看是否注入成功
package springIoc.test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import springIoc.dao.XXDao1;
public class Client {
public static void main(String[] args) {
//Spring容器的初始化
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("springIoc/springxml.xml");
//获取资源
XXDao1 xxDao1 = (XXDao1) ac.getBean("xxDao1");
xxDao1.save();
System.out.println(xxDao1.getName());
}
}
结果为成功
f、@Resource
作用:如同@Autowire和@Qualifier,是规范JSR-250中定义的(JCP)。通过指定bean的名称注入对象。
属性: name:要注入的bean的名称
g、@PostConstruct(了解)
作用:用在初始化方法上。生命周期有关
h、@PreDestroy(了解)
作用:用在销毁方法上。生命周期有关
i、@Configuration和@Bean(了解)
作用:@Configuration指定当前类为配置类,用于加载@Bean的定义。@Bean用于定义bean的名称,用法是@Bean(name="beanName")
注意:该类要被设置在注解自动扫描对应的包下。
a、导入jar包:
spring-test-3.2.0.RELEASE.jar
b、设置Junit运行器和Spring配置文件
步骤:
0、编写一个类(dao层)
package springIoc.dao;
import org.springframework.stereotype.Component;
/**
* @Component是spring的一个注解,它是把XXDao1看做一个组件。
* 就相当于xml中
* @author mch
*
*/
@Component(value="xxDao1")
public class XXDao1 {
public void save() {
System.out.println("SPRING3.XIOC成功了");
}
}
1、设置是spring配置文件
2、进行编写测试类。进行测试
package springIoc.dao;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)//指定新的运行器,该运行前会初始化Spring容器,并注入资源,执行Junit单元测试
@ContextConfiguration(locations={"classpath:springIoc/springxml.xml"})//指定spring容器要加载的配置文件
public class XXDao1Test {
@Autowired
private XXDao1 xxDao1;
@Test
public void test1(){
xxDao1.save();
}
}
结果成功!
其实spring的Ioc原理是 IOC原理:工厂 + 反射 + 配置文件.
那么Spring的Ioc就说到这,后面在继续了解它。