所有内容源自《Spring3.x企业应用开发实战》的学习。留作备查。
目录:
一、标记
二、资源
三、加载配置文件
四、Spring的bean生命周期
五、bean属性注入配置
六、作用域 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");
四、Spring的bean生命周期
/* 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
五、Bean属性注入配置
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();