Spring学习笔记之基本用法和注解

Ioc容器: 控制反转

控制:控制对象的创建及销毁(生命周期)
反转:将对象的控制权交给Ioc容器

约定

  • 所有Bean的生命周期由IoC来管理
  • 所有被依赖的Bean通过构造方法执行注入
  • 被依赖的Bean需要优先创建

实现

  • 实例化Bean
  • 保存Bean
  • 获取Bean
  • 每个Bean有唯一ID与之匹配
import java.lang.reflect.constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.concurrentHashMap;

public class IoCContainer {
	private Map<String, Object> beans = new ConcurrentHashMap<String, Object>
	
	// 根据beanId获取获取一个bean
	public Object getBean(String beanId) {
		return beans.get(beanId);
	}
	
	/* 委托IoC创建一个bean
	 * @param clazz 要创建的bean的class
	 * @param beanId beaId
	 * @param paramBeanIds 要创建的bean的class的构造方法所需要参数的beanIds
	public void setBean(Class<?> clazz, String beanId, String... paramBeanIds) {
		// 1. 组装构造方法所需要的bean值
		Object[] paramValues = new Object[paramBeanId.leangth];
		for(int i=0; i<paramValues.leangth; i++) {
			paramValues[i] = beans.get(i);
		}
		// 2. 调用构造方法实例化bean
		Object bean = null;
		for(Constructor<?> constructor : clazz.getConstructors()) {
			try {
				bean = constuctor.newInstance(paramValues);
			} catch(InstantiationException e) {
			} catch(IllegalAccessException e) {
			} catch(InvocationTargetException e) {
			}
			if (bean == null) {
				throw new RuntimeException("实例化bean失败!");
			}
		}
		
		// 3. 将实例化的bean放入beans
		beans.put(beanId, bean);
	}
}

SpringIoC

引入spring核心包、上下文包、依赖

// pom.xml的配置,引入依赖
<dependencies>
	<groupId>org.springframework</groupId>
	<artifactId>spring-core</artifactId>
	<version>5.1.3.RELEASE</version>
</dependencies>
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context</artifactId>
	<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
	<groupId>junit</groupId>
	<artifactId>junit</artifactId>
	<version>4.12</version>
	<scope>test</scope>
</dependency>

创建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="bean" class="...Bean" />    // ...Bean是Bean的路径
         
 </beas>

获取Spring上下文

ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");

获取Bean

Bean bean = context.getBean("bean", Bean.class);

Spring Bean的相关用法

实例化Bean

通过构造方法实例化Bean

// 先获取上下文对象,在获取Bean
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
Bean bean = context.getBean("bean", Bean.class);

// 配置spring.xml
<bean class="...Bean" id="bean" />
  1. 通过静态方法实例化Bean
// 通过BeanFactory的静态方法获取Bean
public class BeanFactory {
	public static Bean getBean() {
		return new Bean();
	}
}
// 获取Bean
Bean bean = BeanFactory.getBean();

// 配置spring.xml
<bean class="...BeanFactory" factory-method="getBean" id="beanFromFactory" />

通过实例方法实例化Bean

// 通过BeanFactory一般方法获取Bean
public class BeanFactory {
	public Bean getBean() {
		return new Bean();
	}
}
// 获取Bean
BeanFactory beanFactory = new BeanFactory();
Bean bean = new beanFactory.getBean();

// 配置spring.xml
<bean class="...BeanFactory" id="beanFactory" />
<bean class="...Bean" factory-bean="baenFactory" factory-method="getBean" id="beanFromFactory" />

Bean的别名

// 配置多个别名
<bean class="...Bean" id="bean1" name="bean2, bean3" />
Bean bean1 = context.getBean("bean1", Bean.class);    // 实例化bean1
Bean bean2 = context.getBean("bean2", Bean.class);    // 实例化bean2,注意:bean2与bean1是同一个bean
// 为已经实例化的bean起别名
<alias name="bean1" alias="bean3" />

注入Bean

通过构造方法注入Bean

public class Bean {
	private AnotherBean anotherBean;
	private String string;
	public Bean(AnotherBean anotherBean, String string) {
		this.anotherBean = anotherBean;
		this.string = string;
	}
	// 除了构造方法,还有各个属性的get、set方法......
}

// spring.xml的配置
<bean class="...AnotherBean" id="anotherBean" />
<bean class="...Bean" id="bean">
	/* index指明构造方法的第几个属性(与name、type没必要全部写出,只要指明属性就行)
	 * name属性名称
	 * type类名(完整路径)
	 * value属性值,用于基本类型
	 * ref属性值,用于复合类型
	<construcor-arg index="0" name="anotherBean" type="...AnotherBean" ref="anotherBean" />
	<construcor-arg index="1" name="string" type="java.lang.String" value="abcde" />
</bean>

// 简单写法,须在头增加一些信息
xmlns:c="http://www.sprinframework.org/schema/c"
<bean class="...Bean" id="bean" c:anotherBean-ref="anotherBean" c:string="abcde" />

通过set方法注入Bean

// spring.xml的配置
<bean class="...AnotherBean" id="anotherBean" />
<bean class="...Bean" id="bean">
	<property name="anotherBean" ref="anotherBean" />
	<property name="string" value="abcde" />
</bean>

// 简单写法,须在头增加一些信息
xmlns:p="http://www.sprinframework.org/schema/p"
<bean class="...Bean" id="bean" p:anotherBean-ref="anotherBean" p:string="abcde" />

集合类型Bean的注入

public class Bean {
	private List<String> stringList;
	private Map<String, anotherBean> anotherBeanMap;
	// 还有get、set方法......
}

// spring.xml的配置
<bean class="...AnotherBean" id="anotherBean" />
<bean class="...Bean" id="bean">
	<property name="stringList">
		<list>
			<value>abcde</value>    // <ref bean="anotherBean">
		</list>
	</property>
	<property name="anotherBean">
		<map>   
			<entry key="a" value-ref="anotherBean" />    // key / key-ref / value / value-ref
		</map>     // <set><ref bean="anotherBean"></set>
	</property>
</bean>

null值注入

<bean class="...Bean" id="bean">
	<property>
		<null/>
	</property>
</bean>

注入时创建Bean

// spring.xml的配置
<bean class="...AnotherBean" id="anotherBean" />
<bean class="...Bean" id="bean">
	<property name="anotherBean" ref="anotherBean" />
	<property name="string" value="abcde" />
</bean>

// 可以写成如下(注入时创建Bean)
<bean class="...Bean" id="bean">
	<property name="anotherBean">
		<bean class="...AnotherBean" id="anotherBean" />
	</property>
</bean>

Bean作用域

Singleton作用域(单例模式)

// 在同一个上下文环境(context)请求同类型的Bean都会返回同一个bean,不同上下文单例模式失效
<bean class="...Bean" id="bean" scope="singleton" />

prototype作用域(多例模式)

// 同一个上下文环境得到不同bean
<bean class="...Bean" id="bean" scope="prototype" />

Web环境作用域

// 准备工作:建立SpringWeb环境
<servlet>
    <servlet-name>SpringServlet</servlet-name>
    <servlet-class>org.springframeword.web.servlet.DispatcherServlet</servlet-class>
    <init-param>   
    	<param-name>contextConfigLocation</param-name>
    	<param-value>classpath:spring.xml</param-value>
     </init-param>
</servlet>
<servlet-mapping>
      <servlet-name>SpringServlet</servlet-name>
      <url-pattern>/*</url-pattern>
</servlet-mapping>
// 如果不使用DispatcherServlet,则需要增加listener或filter
<listener>    // Servlet2.4以上
	<listener-class>
		org.springframeword.web.context.request.RequestContextListener
	<listener-class>
</listener>

// 准备bean类
@Controller
public class RequestControler {
	@RequestMapping("testRequest")
	@ResponseBody
	public String static() {
		return this.toString();
	}
}
@Controller
public class SessionControler {
	@RequestMapping("testSession")
	@ResponseBody
	public String static() {
		return this.toString();
	}
}
@Controller
public class ApplicationControler {
	@RequestMapping("testApplication")
	@ResponseBody
	public String static() {
		return this.toString();
	}
}

// request作用域:每次请求会获得新的实例
<bean  class="...RequestController" scope="request" />
// session作用域:同一sesiion下获得同一实例,不同session则获得新实例
<bean class="...SessionController" scope="session" />
// application作用域
<bean class="..ApplicationController" scope="application" />

自定义作用域

// 自定义双例模式
public class MyScope implements Scope {
	private Map<String, Object> map1 = new ConcurrentHashMap<String, Object>();
	private Map<String, Object> map2 = new ConcurrentHashMap<String, Object>();
	// 实现Scope接口的方法:get()、remove()等
	public Object get(String name, ObjectFactory<?> ObjectFactory) {
		if (!map1.containsKey(name)) {
			Object o = objectFactory.getObject();
			map1.put(name, o);
			return o;
		}
		if (!map2.containsKey(name)) {
			Object o = objectFactory.getObject();
			map2.put(name, o);
			return o;
		}
		int i = new Random().nextInt(bound 2);
		if (i ==0 ) {
			return map1.get(name);
		} else {
			return map2.get(name);
		}
	}
	public Object remov(String name) {
		if (map2.containsKey(name)) {
			Object o = map2.get(name);
			map2.remov();
			return o;
		}
		if (map1.containsKey(name)) {
			Object o = map1.get(name);
			map1.remov();
			return o;
		}
		return null;
	}
}
 
 // 配置spring.xml
 <bean class="...MyScope" id="myScope" />
 <bean class="org.springframework.bean.factory.config.CustomScopeConfigurer">
 	<property name="scope">
 		<map>
 			<entry key="myScope" value-ref="myScope" />
 		</map>
 	</property>
 </bean>
 <bean class="...Bean" id="bean" scope="myscope" />
 
// 自定义线程作用域:在同一线程下得到同一实例,不同线程下得到不同实例
 <bean class="...MyScope" id="myScope" />
 <bean class="org.springframework.context.suppor.SimpleThreadScope" id="simpleThreadScope" />
 <bean class="org.springframework.bean.factory.config.CustomScopeConfigurer">
 	<property name="scope">
 		<map>
 			<entry key="myScope" value-ref="myScope" />
 			<entry key="simpleThreadScope" value-ref="simpleThreadScope" />
 		</map>
 	</property>
 </bean>
 <bean class="...Bean" id="bean" scope="simpleThreadScope" />

Bean的懒加载

懒加载:多例模式下在context初始化时没有创建Bean,使用context.getBeans()才会实例化Bean
单例模式下在context上下文初始化时Bean已经被加载,多例模式可以在spring.xml文件中设定

// 为某个Bean设定懒加载
<bean class="...Bean" id="bean" lazy-init="true" />
// 为所有的Bean设定懒加载
<beans ... default-lazy-init="true">
	......
</beans>

Bean初始化及销毁逻辑处理

init-method: Bean在初始化后执行某一方法
destroy-method: Bean在销毁之前执行某一方法

// 加入Bean里有onInit()和onDestroy()方法
<bean class="...Bean" id="bean" init-method="onInit" destroy-method="onDestroy" />
// 另一种方式,为所有Bean设定初始化和销毁逻辑处理
<beans ...
			default-init-method="onInit"
			default-destroy-method="onDestroy">
	......
</beans>
// 也可以通过实现InitializingBean和DisponsableBean接口的方式实现,需要实现相关方法

Bean属性继承

// 假定有Class1、Class2继承于ParentClass,attrbute1~3
<bean class="...Class1" id="class1">
	<property name="attrbute1" value="attrbute1" />
	<property name="attrbute2" value="attrbute2" />
	<property name="attrbute3" value="attrbute3" />
	<property name="attrbute4" value="attrbute4" />
</bean>
<bean class="...Class2" id="class2">
	<property name="attrbute1" value="attrbute1" />
	<property name="attrbute2" value="attrbute2" />
	<property name="attrbute3" value="attrbute3" />
	<property name="attrbute5" value="attrbute5" />
</bean>

// 简化代码
<bean class="...ParentClass" id="parentClass" abstract="true">    // abstract说明不需要实例化该方法
	<property name="attrbute1" value="attrbute1" />
	<property name="attrbute2" value="attrbute2" />
	<property name="attrbute3" value="attrbute3" />
</bean>
<bean class="...Class1" id="class1" parent="parentClass">
	<property name="attrbute4" value="attrbute4" />
</bean>
<bean class="...Class2" id="class2" parent="parentClass">
	<property name="attrbute5" value="attrbute5" />
</bean>

// 如果Class1、Class2不是继承于ParentClass,并且有自己的attrbute1~3
<bean id="parentClass" abstract="true">    //删掉 class="...ParentClass"
	<property name="attrbute1" value="attrbute1" />
	<property name="attrbute2" value="attrbute2" />
	<property name="attrbute3" value="attrbute3" />
</bean>
<bean class="...Class1" id="class1">    // 删掉parent="parentClass"
	<property name="attrbute4" value="attrbute4" />
</bean>
<bean class="...Class2" id="class2">
	<property name="attrbute5" value="attrbute5" />
</bean>

SpringIoC注解

获取Bean

// 创建一个class配置文件
@Configuration
public class MyConfiguration {
	// 将一个Bean交由Spring创建并管理
	@Bean("bean1")
	public Bean bean1() {
		return Bean1 = new Bean1();
	}
}
// 获取Spring上下文
ApplicationContext context = new AnnotationConfigApplicationContext(BeanConfiguration.class);
// 获取Bean
Bean1 bean1 = context.getBean("bean1", Bean.class);

// 简化写法
@Configuration
@ComponentScan(value="...package")
public class MyConfiguration {
}
// 开启包扫描
<beans ......>
	<context:component-scan base-package="...package" />
</beans>
// Bean设置
@Component(value="bean")    // 通过构造方法实例化bean,并通过value指定了bean的id
public class Bean {
}
// 其他注解也可以实现类似功能
@Controller: 被标注在Controller层
@Service: 被标注在Service层
@Request: 被标注在Dao层
@conponent: 通用型注解

注入Bean

通过方法注入Bean(构造方法、set方法)

// 1、MyBean类、构造方法或set方法
@Component
public class MyBean {
	private AnotherBean anotherBean;
	@Autowired
	public MyBean( AnotherBean anotherBean) {
		this.anotherBean = anotherBean;
	}
}
// 2、AnotherBean类
@Component
public class AnotherBean {
}
// 3、Spring上下文环境(Configuration类)
@Configuration
@ComponentScan(value="...package")
public class MyConfiguration{
}

通过属性注入

// 环境同上
@Component
public class MyBean {
	@Autowired
	private AnotherBean anotherBean;
}

集合类Bean的型注入

// MyBean类、环境同上
@Component
public class MyBean {
	private List<String> stringList;    // Map一样
	@autowired
	public void setStringList(List<String> stringList) {
	this.stringList = stringList;
	}
}
// MyConfiguration类
@Configuration
@ComponentScan("...package")    // 须在spring.xml开启包扫描
public class MyConfiguration {
	@Bean        // 注入时指定id:@Bean("stringList") --> @Qualifier("stringList") ,优先级高
	public List<String> stringList() {
		List<String> list = new ArrayList<String>();
		list.add("111");
		list.add("222");
		return list;
	}
	// 另外一种方式:spring为类属性自动匹配对应泛型的注入,优先级高于第一种方式
	@Bean
	@Order(1)        // Order指定在List里的顺序
	public String stirng1() {
		return "111";
	}
}

String、Integer等类型直接赋值

@Component
public class MyBean {
	@Value("11111")
	private String string;
	public void setString(String string) {
		this.string = string;
	}
}

SpringIoC容器内置接口实例注入

@Conponent
public class MyBean {
	private ApplicationContext context;
	@autowired        // 可以直接在Bean中直接使用context
	public void setContext(ApplicationContext context) {
		return context;
	}
}
// 可以直接在Bean中直接使用context
ApplicationContext context = new AnnotationConfigApplicationMyConfiguration(MyConfiguration:class);
MyBean myBean = context.getBean(name:"myBean", MyBean.class);
AnotherBean anotherBean = myBean.getContext().getBean(name:"anotherBean", AnotherBean);

设置Bean的作用域

// 第一种方法
@Component
@Scope("singleton")
public class Bean {
}
// 第二中方式
@Configuration
@ComponentScan("...backage")
public class BeanConfiguration {
	@Bean
	@Scope("singleton")
	public Bean bean() {
		return Bean = new Bean();
	}
}

// 注解方式实现自定义作用域
// 定义自己的作用域
public class MyScope implements org.springframework.beans.factory.config.Scope {
	@Override
	public Objeect get(String s, ObjectFactory<?> objectFactory) { ... }
	@Override
	public Objeect remove(String s) { ... }
}
// 配置
@Configuration
@ComponentScan("...backage")
public class BeanConfiguration {
	@Bean
	public MyScope myScope() { return new MyScope(); }
	@Bean()
	public CustomScopeConfigurer customScopeConfigurer(MyScope myScope) {
		CustomScopeConfigurer configurer = new CustomScopeConfigurer();
		configurer.addScope("myScope", myScope);
		return configurer;
	}
	@Bean
	@Scope("myScope")
	public Bean bean() { return Bean = new Bean(); }
}

开启Bean的懒加载

@Configuration
@Lazy    // 第一种方式
public class BeanConfiguration {
	@Bean
	@Lazy    // 第二种方式
	public MyScope myScope() { return new MyScope(); }
}

Bean的初始化和懒加载

// 第一种方式,接口方式
public class Bean implements InitializingBean, DisposableBean {
	@Override
	public void afterPropertiesSet() { ... }
	@Override
	public void destroy() { ... }
}
// 第二种方式
public class Bean {
	public void onInit() { ... }
	public void onDestroy() { ... }
}
@Configuration
public class BeanConfiguration {
	@Bean(initMethod="onInit", desdroyMethod="onDestroy")
	public Bean bean() {
		return new Bean();
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值