所有内容源自《Spring3.x企业应用开发实战》的学习。留作备查。
目录:
六、作用域 scope="singleton|prototype|request|session|blobalSession"
1. @Repository: 最初来自于DDD,表示对storage,retireval,search层的封装。这里多用作traditional J2EE模式中的DAO层表示。
2. @Component: 主要用来被spring自动扫描
3. @Autowired: 自动装配。Spring容器启动时会扫描到该标记,从容器中找到相应的bean注入给该标记对应的Field。(一般都是Field)
4. @Service: 标记三层架构中的中间业务层。
5. @Controller: 用于Spring MVC控制器,类似于struts的Action
6.@RequestMapping: 用于Spring MVC的地址映射,请求根据该标记找到对应的处理逻辑
和XML配置对比:
1)@Component[("xxx")],@Repository,@Service,@Controller相当于<bean id="xxx">标签
2)@Autowired,@Qualifier("xxx")类似于<property>标签。默认按类型注入。而@Resource默认按名称注入。
3)@PostConstruct,@PreDestroy类似于<bean init-method="" destroy-method="">
4) @Scope和@Lazy(true) 类似于<bean scope="" lazy-init="">
// Resource的使用
String path = "C:\\Users\\zhanghui\\Workspaces\\MyEclipse 8.5\\springdemo\\src\\script.sql";
Resource res1 = new FileSystemResource(path);
Resource res2 = new ClassPathResource("script.sql");
System.out.println(res1.getFilename());
System.out.println("length: " + res1.contentLength());
System.out.println("getDescription: " + res1.getDescription());
System.out.println(res2.getFilename());
System.out.println("============ EncodedResource =============");
EncodedResource encRes = new EncodedResource(res1, "UTF-8");
String content = FileCopyUtils.copyToString(encRes.getReader());
System.out.println("Encoded: " + content);
// web环境下的resource
String path = "C:\\Users\\zhanghui\\Workspaces\\MyEclipse 8.5\\springdemo\\src\\script.sql";
Resource res1 = new FileSystemResource(path);
Resource res2 = new ClassPathResource("script.sql");
System.out.println(res1.getFilename());
System.out.println("length: " + res1.contentLength());
System.out.println("getDescription: " + res1.getDescription());
System.out.println(res2.getFilename());
System.out.println("============ EncodedResource 对Resource指定编码格式 =============");
EncodedResource encRes = new EncodedResource(res1, "UTF-8");
String content = FileCopyUtils.copyToString(encRes.getReader());
System.out.println("Encoded: " + content);
// 根据路径模式匹配去获取Resource
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource resources[] = resolver.getResources("classpath:com/baobaotao/**/*.class"); // 或者"classpath*:com/baobaotao/**/*.xml"
for (Resource r : resources) {
System.out.println(r.getFilename());
}
// 非web环境
// BeanFactory
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource res = resolver.getResource("classpath:com/baobaotao/service/ZHTest.xml");
BeanFactory bf = new XmlBeanFactory(res);
Car c = bf.getBean("mycar", Car.class);
c.fun();
// ApplicationContext
ApplicationContext ac = new ClassPathXmlApplicationContext("com/baobaotao/service/ZHTest.xml");
Car c2 = (Car)ac.getBean("mycar");
c2.fun();
// web环境
// 1.配置web.xml
<context-param>
<param-name>contextConfigLoation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
// 2.获取WebApplicationContext
WebApplicationContext wac = (WebApplicationContext)request.getSession().getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
WebApplicationContext wac2 = WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext());
System.out.println(wac == wac2);
Car c = wac.getBean("mycar");
/*
1.Bean自身方法: 构造函数,setter,init-method,destroy-method
2. bean级生命周期接口: BeanNameAware,BeanFactoryAware,InitializingBean,DisposableBean.
3. 容器级别的后处理器:BeanPostProcessor
*/
// 1.定义bean
public class Car implements BeanNameAware, BeanFactoryAware, InitializingBean, DisposableBean{
private String name;
public void setName(String name) {
System.out.println("Car.setName("+name+") called!!");
this.name = name;
}
public Car() {
System.out.println("Car.Car() called!!");
}
public void fun() {
System.out.println("Car.fun() called!! I am " + this.name);
}
public void init_method() {
System.out.println("Car.init_method() called");
}
public void destroy_method() {
System.out.println("Car.destroy_method() called");
}
public void setBeanName(String name) {
System.out.println("BeanNameAware.BeanNameAware(" + name + ") called");
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("BeanFactoryAware.setBeanFactory() called");
}
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean.afterPropertiesSet() called");
}
public void destroy() throws Exception {
System.out.println("DisposableBean.destroy() called");
}
}
// 2.定义后处理器
public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter{
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
if ("mycar".equals(beanName)) {
System.out.println("MyInstantiationAwareBeanPostProcessor.postProcessAfterInitialization() called");
}
return bean;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName)
throws BeansException {
if ("mycar".equals(beanName)) {
System.out.println("MyInstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() called");
}
return true;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
if ("mycar".equals(beanName)) {
System.out.println("MyInstantiationAwareBeanPostProcessor.postProcessBeforeInitialization() called");
}
return bean;
}
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass,
String beanName) throws BeansException {
if ("mycar".equals(beanName)) {
System.out.println("MyInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() called");
}
return null;
}
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs,
PropertyDescriptor[] pds, Object bean, String beanName)
throws BeansException {
if ("mycar".equals(beanName)) {
System.out.println("MyInstantiationAwareBeanPostProcessor.postProcessPropertyValues() called");
}
return pvs;
}
}
// 3. 配置
<bean id="mycar" class="com.baobaotao.service.Car" init-method="init_method" destroy-method="destroy_method" scope="prototype">
<property name="name" value="jack"></property>
</bean>
// 4.实例化容器并获取bean,观察生命周期方法的执行
// BeanFactory
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource res = resolver.getResource("classpath:com/baobaotao/service/ZHTest.xml");
BeanFactory bf = new XmlBeanFactory(res);
((ConfigurableBeanFactory)bf).addBeanPostProcessor(new MyInstantiationAwareBeanPostProcessor());
Car c = bf.getBean("mycar", Car.class);
c.setName("allei");
c.fun();
System.out.println("===================");
Car c2 = bf.getBean("mycar", Car.class);
System.out.println("c1==c2" + (c==c2));
((XmlBeanFactory)bf).destroySingletons();
// 5.输出:
MyInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() called
Car.Car() called!!
MyInstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() called
MyInstantiationAwareBeanPostProcessor.postProcessPropertyValues() called
Car.setName(jack) called!!
BeanNameAware.BeanNameAware(mycar) called
BeanFactoryAware.setBeanFactory() called
MyInstantiationAwareBeanPostProcessor.postProcessBeforeInitialization() called
InitializingBean.afterPropertiesSet() called
Car.init_method() called
MyInstantiationAwareBeanPostProcessor.postProcessAfterInitialization() called
Car.setName(allei) called!!
Car.fun() called!! I am allei
===================
Car.Car() called!!
MyInstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() called
MyInstantiationAwareBeanPostProcessor.postProcessPropertyValues() called
Car.setName(jack) called!!
BeanNameAware.BeanNameAware(mycar) called
BeanFactoryAware.setBeanFactory() called
MyInstantiationAwareBeanPostProcessor.postProcessBeforeInitialization() called
InitializingBean.afterPropertiesSet() called
Car.init_method() called
MyInstantiationAwareBeanPostProcessor.postProcessAfterInitialization() called
c1==c2false
// ********************************
// 6.如果使用ApplicationContext进行初始化,和用BeanFactory初始化的区别:
// -- 可以定义BeanFactoryPostProcessor后处理器,让我们有机会在获取bean之前进行再次修改
// -- 所有的后处理器不需要通过编程的方式加到容器中,只需要直接在配置文件里面进行普通bean的配置即可。spring会自动感知这些后处理器
// ********************************
// 6.1 定义BeanFactoryPostProcessor
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor{
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition bd = beanFactory.getBeanDefinition("mycar");
bd.getPropertyValues().addPropertyValue("name", "xxxxxxxx");
System.out.println("MyBeanFactoryPostProcessor.postProcessBeanFactory() called");
}
}
// 6.2 配置后处理器
<bean id="myBeanFactoryPostProcessor" class="com.baobaotao.service.MyBeanFactoryPostProcessor"></bean>
<bean id="myInstantiationAwareBeanPostProcessor" class="com.baobaotao.service.MyInstantiationAwareBeanPostProcessor"></bean>
// 6.3 ApplicationContext初始化
ApplicationContext ac = new ClassPathXmlApplicationContext("com/baobaotao/service/ZHTest.xml");
Car c2 = (Car)ac.getBean("mycar");
c2.setName("allei");
c2.fun();
System.out.println("===================");
Car c3 = (Car)ac.getBean("mycar");
c3.setName("Nani");
c3.fun();
// 6.4 输出
MyBeanFactoryPostProcessor.postProcessBeanFactory() called
MyInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() called
Car.Car() called!!
MyInstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() called
MyInstantiationAwareBeanPostProcessor.postProcessPropertyValues() called
Car.setName(xxxxxxxx) called!!
BeanNameAware.BeanNameAware(mycar) called
BeanFactoryAware.setBeanFactory() called
MyInstantiationAwareBeanPostProcessor.postProcessBeforeInitialization() called
InitializingBean.afterPropertiesSet() called
Car.init_method() called
MyInstantiationAwareBeanPostProcessor.postProcessAfterInitialization() called
Car.setName(allei) called!!
Car.fun() called!! I am allei
===================
Car.Car() called!!
MyInstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() called
MyInstantiationAwareBeanPostProcessor.postProcessPropertyValues() called
Car.setName(xxxxxxxx) called!!
BeanNameAware.BeanNameAware(mycar) called
BeanFactoryAware.setBeanFactory() called
MyInstantiationAwareBeanPostProcessor.postProcessBeforeInitialization() called
InitializingBean.afterPropertiesSet() called
Car.init_method() called
MyInstantiationAwareBeanPostProcessor.postProcessAfterInitialization() called
Car.setName(Nani) called!!
Car.fun() called!! I am Nani
1. Spring IOC容器主要是用来对bean进行管理,主要使用反射,在使用后处理器时使用了动态代理。
基本原理就是通过反射的方式取创建bean的实例(prototype每次都会创建,singleton方式只创建一次)。
bean的属性注入分为setter和构造方法注入(还有工厂注入,很少用)。也是使用反射的方式取注入。
2. Spring注入方式
1) 字面常量。针对基本类型、包装类和String。 主要特殊字符要转义: <(<) >(>) &(&) "(") '(')
2) 引用其他bean。 <ref bean="otherBeanId" />
3) 内部bean。
<bean id="outerBean" class="...">
<property name="car">
<bean class="..." /> <!-- 独立的bean定义 -->
</property>
</bean>
4) null值 <property name="car"> <null/> </property>
5) list属性 (也适用于基本类型、包装类型、string类型的数组。如String[], int[], Integer[])
<property name="mylist">
<list>
<value>list_item1</value>
<value>list_item2</value>
<value>list_item3</value>
</list>
</property>
6) set属性
<property name="myset">
<set>
<value>list_item1</value>
<value>list_item2</value>
<value>list_item3</value>
</set>
</property>
7) map属性
<property name="mymap">
<map>
<entry>
<key><value>key1</value> </key>
<value>value1</value>
</entry>
<entry>
<key><value>key2</value> </key>
<value>value2</value>
</entry>
<entry key="map_key3" value="map_value3" />
<!-- 对于key-value都是对象的情况
<entry>
<key><ref bean="xx" /> </key>
<ref bean="xx"/>
</entry>
-->
</map>
</property>
8) properties属性
<property name="myprops">
<props>
<prop key="key1">value1</prop>
<prop key="key2">value2</prop>
<prop key="key3">value3</prop>
</props>
</property>
七、FactoryBean
// FactoryBean用来控制bean的实例化过程,不再交给spring容器去实例化
public class CarFactoryBean implements FactoryBean<Car> {
public Car getObject() throws Exception {
Car c = new Car();
c.setColor("black");
c.setName("Ford");
return c;
}
public Class<?> getObjectType() {
return Car.class;
}
public boolean isSingleton() {
return false;
}
}
// 配置
<bean id="mycar4" class="com.baobaotao.service.CarFactoryBean"/>
// 使用
ApplicationContext ac = new ClassPathXmlApplicationContext("com/baobaotao/service/ZHTest.xml");
Car c4 = (Car)ac.getBean("mycar4"); // 实际上市调用FactoryBean的getObject()方法
c4.fun();