SSM框架学习-2
- Spring的工厂类
- Spring的Bean管理(XML方式)
- Spring的属性注入(XML方式)
- Spring的Bean管理(注解方式)
- Spring的属性注入(注解方式)
1.Spring的工厂类
通过ApplicationContext接口,ClassPathXmlApplicationContext来实现类,其实也可以通过FileSystemXmlApplicationContext来实现,区别在于前者是工程中的配置文件,后者则是系统中的配置文件(通过路径)。老版本的叫做BeanFatory,如今的ApplicationContext是他的子接口,前者会在getBean时创建实例,后者则是在加载配置文件时创建实例。 下面看一下用FileSystemXmlApplicationContext创建工厂类,以及用BeanFatory方式创建工厂类
@Test
/**
* 读取磁盘中的配置文件
*/
public void demo3(){
//创建Spring工厂
ApplicationContext applicationContext = new FileSystemXmlApplicationContext("c:\\applicationContext.xml");
//通过工厂获得类
Myservice myservice = (Myservice)applicationContext.getBean("myserviceImp");
myservice.sayHello();
}
@Test
/**
* 传统方式创建工厂类
*/
public void demo4(){
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
Myservice myservice = (Myservice)beanFactory.getBean("myserviceImp");
myservice.sayHello();
}
@Test
/**
* 传统方式创建工厂类,读取磁盘文件
*/
public void demo5(){
BeanFactory beanFactory = new XmlBeanFactory(new FileSystemResource("c:\\applicationContext.xml"));
Myservice myservice = (Myservice)beanFactory.getBean("myserviceImp");
myservice.sayHello();
}
2.Spring的Bean管理(XML方式)
三种实例化Bean的方式
- 使用类构造器实例化(默认无参数)
- 使用静态工厂方法实例化(简单工厂模式)
- 使用实例工厂方法实例化(工厂方法模式)
1.使用类构造器实例化(默认无参数)
//bean1
package com.snake_lvyonghao.demo2;
/**
* Bean
* 采用无参数的构造方法
*/
public class Bean1 {
public Bean1(){
System.out.println("Bean1被实例化了");
}
}
------------------------
//配置文件
<!--第一种,无参数构造器-->
<bean id="bean1" class="com.snake_lvyonghao.demo2.Bean1"></bean>
----------------------------
//SpringDemo2
@Test
public void demo1(){
//创建工厂
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//通过工厂创建类
Bean1 bean1 = (Bean1)applicationContext.getBean("bean1");
}
2.使用静态工厂方法实例化(简单工厂模式)
创建一个工厂类,设置静态工厂方法创建类,配置文件中添加actory-method属性调用工厂类的工厂方法。
//Bean2
package com.snake_lvyonghao.demo2;
/**
* Bean实例化三种方式,静态工厂方法实例化
*/
public class Bean2 {
}
--------------------
//BeanFactory
package com.snake_lvyonghao.demo2;
/**
* Bean2的静态工厂
*/
public class Bean2Factory {
public static Bean2 creativeBean2(){
System.out.println("Bean2Fatory已经执行了");
return new Bean2();
}
}
-------------------
//配置文件
<!--第二种,静态工厂方法-->
<bean id="bean2" class="com.snake_lvyonghao.demo2.Bean2Factory" factory-method="creativeBean2"></bean>
-----------------------
//SpringDemo2
@Test
public void demo2(){
//创建工厂
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//通过工厂创建类
Bean2 bean2 = (Bean2) applicationContext.getBean("bean2");
}
3.使用实例工厂方法实例化(工厂方法模式) 和静态工厂方法的区别在于在配置文件中需要先生成工厂实例再生成实例类,在配置文件中添加factory-bean属性,确定实例工厂(就是在配置文件中先生成的工厂实例的Bean的id)。
//Bean3
package com.snake_lvyonghao.demo2;
/**
* 实例工厂实例化
*/
public class Bean3 {
}
------------------------
//BeanFactory
package com.snake_lvyonghao.demo2;
/**
* Bean3的实例工厂
*/
public class Bean3Factory {
public Bean3 creative(){
System.out.println("Bean3Fatory方法执行了");
return new Bean3();
}
}
-------------------------------
//配置文件
<!--第三种,实例工厂的方式-->
<bean id="bean3Factory" class="com.snake_lvyonghao.demo2.Bean3Factory"></bean>
<bean id="bean3" factory-bean="bean3Factory" factory-method="creative"></bean>
---------------------------------
//SpringDemo2
@Test
public void demo3(){
//创建工厂
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//通过工厂创建类
Bean3 bean3 = (Bean3) applicationContext.getBean("bean3");
3.Bean的配置
- id和name
一般情况下,装配Bean时,通过指定一个id属性作为Bean的名称 id属性在IOC容器中必须是唯一的 如果Bean的名称中有特殊字符,需要用name,eg:/bean
- class
class用于设置一个类的完全路径名称,主要作用是IOC容器生成类的实例
- Bean的作用域
类别 | 说明 |
---|---|
singleton | 在Spring 容器中仅存在一个Bean实例,Bean以单例的方式存在 |
prototype | 每次调用getBean()都会返回一个新的实例 |
reques | 每次HTTP请求都会创建一个新的Bean,作用域仅适用于WebApplicationContext环境 |
session | 同Http Session共享一个Bean,不同Http Session使用不同的Bean,作用域仅适用于WebApplicationContext环境 |
//配置文件
<bean id="person" class="com.snake_lvyonghao.demo3.Person" scope="prototype"></bean>
<bean id="person" class="com.snake_lvyonghao.demo3.Person"></bean>
//测试只用一个不用的请注释掉
-----------------------------------
//Person
package com.snake_lvyonghao.demo3;
public class Person {
}
-----------------------------------
//SpringDemo3
@Test
public void demo1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person1 = (Person) applicationContext.getBean("person");
Person person2 = (Person) applicationContext.getBean("person");
//查看地址,说明创建的是单例的,多例的
System.out.println(person1);
System.out.println(person2);
}
- Spring容器中Bean生命周期
Spring初始化Bean或销毁Bean时,有时需要做一些处理工作,因此Spring可以创建和销毁Bean的时候调用Bean的两个生命周期方法,init-method=”init”,destory-method=”destroy”,当Bean被载入容器的时候调用init,当Bean被从容器中删除的时候调用destroy(scope=singleton有效)
//Man
package com.snake_lvyonghao.demo3;
public class Man {
public Man(){
System.out.println("MAN被实例化了");
}
public void setup(){
System.out.println("MAN被初始化了");
}
public void teardown(){
System.out.println("MAN被销毁了");
}
}
-----------------------
//配置文件
<bean id="man" class="com.snake_lvyonghao.demo3.Man" init-method="setup" destroy-method="teardown"></bean>
-------------------------
//SpringDemo3
@Test
public void demo2(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Man man = (Man) applicationContext.getBean("man");
System.out.println(man);
}
完整的Bean生命周期(先看看就好)
1.instantiate bean对象实例化
2.populate properties封装属性
3.如果Bean实现BeanNameAware执行setBeanName
4.如果Bean实现BeanFactoryAware或者ApplicationContextAware设置工厂setBeanFactory或者上想问对象setApplicationContext
5.如果存在类实现 BeanPostProcessor(后处理Bean),执行posetProcessBeforeInitalization(重点)
6.如果Bean实现InitializingBean执行afterPropertiesSet
7.调用<bean init-method="init">指定初始化方法init
8.如果存在类实现BeanPostProcessor(处理Bean),执行postProcessAfterInitialization
9.处理业务(自身方法)
10.如果Bean实现DisposableBean执行Destroy
11.调用<bean destroy-method="customerDestory"> 指定销毁方法customerDestroy
代码如下:
//MyBeanPostProcesser
package com.snake_lvyonghao.demo3;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("第八步,初始化后方法");
return bean;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("第五步,初始化前方法");
return bean;
}
}
//Man
package com.snake_lvyonghao.demo3;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class Man implements BeanNameAware, ApplicationContextAware,InitializingBean, DisposableBean {
private String name;
public void setName(String name) {
System.out.println("第二步,设置属性");
this.name = name;
}
public Man(){
System.out.println("第一步,对象实例化");
}
public void setup(){
System.out.println("第七步");
}
public void teardown(){
System.out.println("第十一步,执行指定的销毁方法");
}
@Override
public void setBeanName(String s) {
System.out.println("第三步,设置Bean 名称:" + name);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("第四步,了解工厂信息");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("第六步,属性设置后");
}
public void run(){
System.out.println("第九步,自身业务方法");
}
@Override
public void destroy() throws Exception {
System.out.println("第十步,执行销毁方法");
}
}
//配置文件
<bean id="man" class="com.snake_lvyonghao.demo3.Man" init-method="setup" destroy-method="teardown">
<property name="name" value="zhangsan"></property>
</bean>
<bean class="com.snake_lvyonghao.demo3.MyBeanPostProcessor"></bean>
通过对MyBeanPostProcessor文件的修改,实现初始化类的增强,具体代码请看Github中的UserDao,UserDaoImp,MyBeanPostProcessor。(这部分和后期的AOP面向切面的编程有关)。 —
Spring属性注入
- 对于了成员变量,注入方式有三种
1.构造函数注入2.属性setter方法注入,3.接口注入,Spring支持前两种
构造函数注入:在原类中定义构造函数,并在配置文件中填写constructor-arg标签,根据name和value添加属性
//配置文件
<bean id="user" class="com.snake_lvyonghao.demo4.User">
<constructor-arg name="name" value="张三"></constructor-arg>
<constructor-arg name="age" value="20"></constructor-arg>
</bean>
--------------------------
//User
package com.snake_lvyonghao.demo4;
public class User {
private String name;
private Integer age;
public User(String name,Integer age){
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
---------------------------
//SpringDemo4
@Test
public void demo1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) applicationContext.getBean("user");
System.out.println(user);
}
使用set方法注入,在Spring配置文件中,通过
设置注入的属性同样是name属性名字,value属性值,ref引入其他Bean的id或name
//配置文件
<bean id="person" class="com.snake_lvyonghao.demo4.Person">
<property name="name" value="李四"></property>
<property name="age" value="25"></property>
<property name="cat" ref="cat"></property>
</bean>
<bean id="cat" class="com.snake_lvyonghao.demo4.Cat">
<property name="name" value="Ketty"></property>
</bean>
---------------------------
//Person
package com.snake_lvyonghao.demo4;
public class Person {
private String name;
private Integer age;
private Cat cat;
public Cat getCat() {
return cat;
}
public void setCat(Cat cat) {
this.cat = cat;
}
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", cat=" + cat +
'}';
}
}
----------------------------------
//Cat
package com.snake_lvyonghao.demo4;
public class Cat {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public java.lang.String toString() {
return "Cat{" +
"name=" + name +
'}';
}
}
--------------------------------
//SpringDemo4
@Test
public void demo2(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person) applicationContext.getBean("person");
System.out.println(person.toString());
}
p名称空间注入:
使用p命名空间,p:<属性名>="xxx"引入常量,p:<属性名>-ref="xxx"引入其他Bean对象 具体代码见GitHub中applicaContext,src.com.snake_lvyonghao.demo4中PerSon,Cat,SpringDemo4属性名>属性名>
SpEL注入(属性注入比较复杂的情况下):
语法: #{表达式}
<bean id="" value="#{表达式}">
# {'hello'} : 使用字符串
# {beanID} : 使用另一个beanID
# {beanId.content.toUpperCase()} : 使用指定名属性,并用其方法
# {T(java.lang.Math).PI} : 使用静态字段或方法
复杂类型的属性注入
数组类型的属性注入. List集合类型的属性注入. Set集合类型的属性注入 . Map集合类型的属性注入. Properties类型的属性注入.
//配置文件
<bean id="collectionbean" class="com.snake_lvyonghao.demo5.CollectionBean">
<property name="arrs">
<list>
<value>aaa</value>
<value>ddd</value>
<value>ccc</value>
</list>
</property>
<property name="list">
<list>
<value>111</value>
<value>222</value>
<value>333</value>
</list>
</property>
<property name="set">
<set>
<value>ddd</value>
<value>eee</value>
<value>fff</value>
</set>
</property>
<property name="map">
<map>
<entry key="aaa" value="1"></entry>
<entry key="bbb" value="2"></entry>
<entry key="vvv" value="3"></entry>
<entry key="ccc" value="4"></entry>
</map>
</property>
<property name="properties">
<props>
<prop key="username">root</prop>
<prop key="password">123</prop>
</props>
</property>
</bean>
-------------------
//CollectionBean
package com.snake_lvyonghao.demo5;
import java.util.*;
public class CollectionBean {
private String[] arrs;
private List<String> list;
private Set<String> set;
private Map<String,Integer> map;
private Properties properties; //属性类型
public String[] getArrs() {
return arrs;
}
public List<String> getList() {
return list;
}
public Set<String> getSet() {
return set;
}
public Map<String, Integer> getMap() {
return map;
}
public Properties getProperties() {
return properties;
}
public void setArrs(String[] arrs) {
this.arrs = arrs;
}
public void setList(List<String> list) {
this.list = list;
}
public void setSet(Set<String> set) {
this.set = set;
}
public void setMap(Map<String, Integer> map) {
this.map = map;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
@Override
public String toString() {
return "CollectionBean{" +
"arrs=" + Arrays.toString(arrs) +
", list=" + list +
", set=" + set +
", map=" + map +
", properties=" + properties +
'}';
}
}
-------------------------------------------------------------
//SpringDemo5
@Test
public void deom1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
CollectionBean collectionBean = (CollectionBean) applicationContext.getBean("collectionbean");
System.out.println(collectionBean);
}
4.用注解定义Bean
- @Component 描述Spring 框架中的Bean
- @Repository 用于对DAO实现类进行标注
- @Service 用于对Service实现类进行标注
- @Controller 用于对Controller实现类进行标注
- @Autowired 进行自动注入(默认按照类型进行注入,如果存在两个相同Bean类型相同,则按照名称注入)
- @Autowired注入时可以针对成员变量或set方法
- 通过@Autowired的required属性,设置一定要找的匹配的Bean
- 使用@Qualifier指定注入Bean的名称
- @Resource 可以代替@Autowired和@Qualifiter
- @Value 可以为普通属性注入
- @PostConstruct Bean生命周期方法,初始化
- @PreDestroy Bean生命周期方法,销毁
- @Scope 约束Bean的作用域
@Component 描述Spring框架中的Bean,使用时写在实现类前面
//SpringDemo1
package com.snake_lvyonghao.demo1;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class springDemo1 {
@Test
public void demo1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) applicationContext.getBean("userService");
userService.sayHello("lvyonghao");
}
}
--------------------------------------------------------------
//UserService
package com.snake_lvyonghao.demo1;
import org.springframework.stereotype.Component;
@Component("userService")
public class UserService {
public void sayHello(String name){
System.out.println("Hello" + name);
}
}
----------------------------------------------------------
//配置文件
<?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="com.snake_lvyonghao.demo1"></context:component-scan>
</beans>
其他的标签同理。
属性注入
//UserService
package com.snake_lvyonghao.demo1;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component("userService")
public class UserService {
@Value("米饭")
private String something;
public UserService(UserDao userDAO) {
this.userDAO = userDAO;
}
public void sayHello(String name){
System.out.println("Hello" + name);
}
public void eat(){
System.out.println("eat" +something);
}
@Autowired
@Qualifier("userDao111")
// @Resource(name="userDAO")
private UserDao userDAO;
public void save(){
System.out.println("Servive保存用户");
userDAO.save();
}
}
------------------------------------------------------
//UserDao
package com.snake_lvyonghao.demo1;
import org.springframework.stereotype.Repository;
@Repository("userDao111")
public class UserDao {
public void save(){
System.out.println("DAO保存用户");
}
}
-----------------------------------------------------------
//SpringDemo1
@Test
public void demo2(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) applicationContext.getBean("userService");
userService.eat();
}
@Test
public void demo3(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) applicationContext.getBean("userService");
userService.save();
}
//Bean1
package com.snake_lvyonghao.demo2;
import org.springframework.stereotype.Component;
import javax.annotation.*;
@Component("bean1")
public class Bean1 {
public void say(){
System.out.println("say...");
}
@PostConstruct
public void init(){
System.out.println("initBean...");
}
@PreDestroy
public void detory(){
System.out.println("Destory...");
}
}
-----------------------------
//Bean2
package com.snake_lvyonghao.demo2;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component("bean2")
@Scope("prototype")
public class Bean2 {
}
----------------------------------------
//SpringDemo2
package com.snake_lvyonghao.demo2;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringDemo2 {
@Test
public void demo1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Bean1 bean1 = (Bean1) applicationContext.getBean("bean1");
bean1.say();
}
@Test
public void demo2(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Bean2 bean1 = (Bean2) applicationContext.getBean("bean2");
Bean2 bean2 = (Bean2) applicationContext.getBean("bean2");
System.out.println(bean1);
System.out.println(bean2);
}
}