Spring IOC 配置分析
发布时间:2021-12-09 20:06:40 所属栏目:教程 来源:互联网
导读:1 IOC概述 1.1 IOC概念 IOC中文是控制反转,即是某一接口具体实现类的选择控制权从调用类中移除,转交给第三方决定。从而解除了某一接口对实现类的直接依赖。 1.2 IOC类型 主要分为构造函数注入,属性注入,接口注入 构造函数注入 public class Bar { privat
1 IOC概述 1.1 IOC概念 IOC中文是控制反转,即是某一接口具体实现类的选择控制权从调用类中移除,转交给第三方决定。从而解除了某一接口对实现类的直接依赖。 1.2 IOC类型 主要分为构造函数注入,属性注入,接口注入 构造函数注入 public class Bar { private Foo foo; public Bar(Foo foo) { this.foo = foo; } } 属性注入 public class Bar { private Foo foo; public void setFoo(Foo foo) { this.foo = foo; } } 接口注入 public interface BarInterface { void setFoo(Foo foo); } public class Bar implements BarInterface { private Foo foo; public void setFoo(Foo foo) { this.foo = foo; } } 此种方式和属性注入没有明显区别,但是却增加了一个接口,这不利于项目后期的维护,因此不建议使用! 1.3 spring的IOC配置 <?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="foo" class="org.acy.di.Foo"/> <bean id="bar" class="org.acy.di.Bar"> <property name="foo" ref="foo"/> </bean> </beans> 2 spring的资源访问 2.1 资源抽象接口 Spring的Resource接口,使应用访问底层资源更加便捷。 主要方法: -boolean exists() 是否存在 -boolean isOpen() -URL getURL() -File getFile() -InputStream getInputStream() 这个接口下面主要的实现类有: ByteArrayResource:内存资源 ClassPathResource:类路径下的资源 FileSystemResource:文件系统资源 InputStreamResource:输入流资源 ServletContextResource:Web容器上下文资源 UrlResource:远程资源 测试1 public class FileSourceExample { public static void main(String[] args) { String filePath = "C:UsersAdministratorIdeaProjectsspringc03srcmainresources1.txt"; Resource resource1 = new FileSystemResource(filePath); System.out.println(resource1.getFilename()); Resource resource = new ClassPathResource("1.txt"); System.out.println(resource.getFilename()); } } 测试2 <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <% Resource resource = new ServletContextResource(application, "/WEB-INF/classes/1.txt"); %> <%=resource.getFilename()%> <%=WebUtils.getTempDir(application).getAbsolutePath()%> </body> </html> 测试3 public class EncodedTest { public static void main(String[] args) throws IOException { Resource resource = new ClassPathResource("1.txt"); EncodedResource encodedResource = new EncodedResource(resource,"utf-8"); String s = FileCopyUtils.copyToString(encodedResource.getReader()); System.out.println(s); } } 注:资源加载时默认采用系统编码读取资源,如果需要转码,可用EncodedResource 2.2资源加载 资源地址表达式 classpath: 从类的跟路径加载 file: 从文件路径 http: http协议 ftp: ftp协议加载 没有前缀 则根据当前实用的ApplicationConext实现类决定 "classpath*:"相对于"classpath:"的优势在于:如果有同包名的资源文件,分别打成了两个jar包【a.jar和b.jar】。 用"classpath:"只加在a.jar中的资源文件。用"classpath*:"会加载a b两个jar包的配置文件 匹配符 ? :一个字符 * :多个字符 ** :多级目录 资源加载器 ResourceLoader:可以根据资源地址加载一个资源,但不支持匹配符 ResourcePatternResolver:支持匹配符 PathMatchingResourcePatternResolver:Spring的标准实现,也支持匹配符 public class ResolverTest { public static void main(String[] args) throws IOException { ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); Resource[] resources = resolver.getResources("classpath*:org/acy/**/*.xml"); for (Resource resource : resources) { System.out.println(resource.getFilename()); } } } 3 BeanFactory与ApplicationContext 3.1 BeanFactory解读 BeanFactory是一个工厂,用于创造各种类型的对象。 BeanFactory体系结构 BeanFactory:底层接口 ListableBeanFactory:增加访问容器中Bean基本信息的方法 如bean的个数,是否包含等。 HierarchicalBeanFactory:父子容器级联接口,使子容器可以访问父容器。 ConfigurableBeanFactory:重要接口,增强了IOC的定制化,加入了类装载器、属性编辑器、容器初始化后置处理器的方法 AutowireCapableBeanFactory:加入自动装配 测试 public class BeanFactoryTest { public static void main(String[] args) { ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); Resource resource = resolver.getResource("classpath:applicationContext.xml"); BeanFactory beanFactory = new XmlBeanFactory(resource); System.out.println("BeanFactory 初始化完成"); Car car = beanFactory.getBean("car", Car.class); System.out.println(car); } } 注:以上使用了XmlBeanFactory,其为上面那些接口的最终实现类。用BeanFactory会导致Bean在容器启动时候不会主动初始化,而是等到第一次使用时候在初始化。 3.2 ApplicationContext介绍 主要实现类有ClasspathXmlApplicationContext与FileSystemXmlApplicationContext,且ApplicationContext所有实现类都实现了ResourcePatternResolver接口,可以接受匹配符表达式加载资源文件。 并且ConfigurableApplicationContext还加入了refresh()和close(),用于刷新和关闭容器。 ApplicationContext是在容器启动时初始化所有Bean 注解配置 @Configuration public class Beans { @Bean(name = "car") public Car buildCar() { Car car = new Car(); car.setBrand("三轮车"); car.setColor("red"); car.setMaxSpeed(200); return car; } } public class AnnoTest { public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(Beans.class); Car car = context.getBean("car", Car.class); System.out.println(car); } } WebApplicationContext WebApplicationContext是存储在ServletContext中,所有可以再任何代码中取出实用。 WebApplicationContextUtils.getWebApplicationContext(ServletContext sc) WebApplicationContext初始化 在Web.xml配置监听器 ContextLoaderListener <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> 如果不支持Listener,则可以使用ContextLoaderServlet 以上配置,Spring会默认采用XmlWebApplicationContext,如果要采用注解,可以实用如下配置 <context-param> <param-name>contextClass</param-name> <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value> </context-param> <context-param> <param-name>contextConfigLocation</param-name> <param-value>org.acy.anno.Beans</param-value> </context-param> 4 Bean生命周期 Bean的作用范围 实例化Bean时所经历的一系列阶段 4.1 BeanFactory的生命周期 关键点: Bean自身的方法:如实例化,setter,或者init method和destroy method Bean级别生命周期接口方法: BeanNameAware BeanFactoryAware InitializingBean和DisposableBean 重点 容器级生命周期接口方法 InstantiationAwareBeanPostProcessor和BeanPostProcessor,这些接口的实现类为单独的组件,实现后注册到容器上即可。[属于插件机制] 可以注册多个同种接口的实现类,但是必须实现Ordered接口排序。 新版本中还加入了InstantiationAwareBeanPostProcessorAdapter抽象类 例子 public class Cat implements BeanFactoryAware,BeanNameAware,InitializingBean,DisposableBean { private String brand; private String color; private int maxSpeed; public Cat() { } public Cat(String brand, String color, int maxSpeed) { this.brand = brand; this.color = color; this.maxSpeed = maxSpeed; } public void introduce() { System.out.println(this.toString()); } public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public int getMaxSpeed() { return maxSpeed; } public void setMaxSpeed(int maxSpeed) { this.maxSpeed = maxSpeed; } @Override public String toString() { return "Car{" + "brand='" + brand + ''' + ", color='" + color + ''' + ", maxSpeed=" + maxSpeed + '}'; } private BeanFactory beanFactory; public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.out.println("setBeanFactory"); this.beanFactory = beanFactory; } private String beanName; public void setBeanName(String s) { System.out.println("setBeanName"); this.beanName = s; } public void destroy() throws Exception { System.out.println("destroy"); } public void afterPropertiesSet() throws Exception { System.out.println("afterPropertiesSet"); } public void myInit(){ System.out.println("myInit"); this.setMaxSpeed(240); } public void myDestroy(){ System.out.println("myDestroy"); } } public class MyBeanPostProcessor implements BeanPostProcessor { public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if ("cat".equals(beanName)) { Cat cat = (Cat) bean; if (cat.getColor() == null) { System.out.println("color 为空 设为黑色"); cat.setColor("black"); } } return bean; } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if ("cat".equals(beanName)) { Cat cat = (Cat) bean; if (cat.getMaxSpeed() > 200) { System.out.println("speed great then 200"); cat.setMaxSpeed(200); } } return bean; } } public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter { @Override public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException { if ("cat".equals(beanName)){ System.out.println("postProcessBeforeInstantiation"); } return null; } @Override public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { if ("cat".equals(beanName)){ System.out.println("postProcessAfterInstantiation"); } return true; } @Override public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { if ("cat".equals(beanName)){ System.out.println("postProcessPropertyValues"); } return pvs; } } public class BeanCycle { public static void main(String[] args) { Resource res = new ClassPathResource("applicationContext.xml"); XmlBeanFactory beanFactory = new XmlBeanFactory(res); ConfigurableBeanFactory configurableBeanFactory = beanFactory; configurableBeanFactory.addBeanPostProcessor(new MyBeanPostProcessor()); configurableBeanFactory.addBeanPostProcessor(new MyInstantiationAwareBeanPostProcessor()); Cat cat = beanFactory.getBean("cat", Cat.class); System.out.println(cat); cat.setColor("yellow"); Cat c2 = beanFactory.getBean("cat", Cat.class); System.out.println(cat == c2); beanFactory.destroySingletons(); } } 以上例子简单打印了一些spring的生命周期信息,并且有一些先后顺序。在新版本中 init method和destroy method的配置改为@PostConstruct和@PreDestroy注解配置。 BeanPostProcessor是一个扩展Spring的重要接口。 4.2 ApplicationContext的生命周期 加入了一个新接口ApplicationContextAware 用户注入ApplicationContext。 public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { BeanDefinition beanDefinition = beanFactory.getBeanDefinition("cat"); beanDefinition.getPropertyValues().addPropertyValue("brand","奇瑞qq"); System.out.println("postProcessBeanFactory"); } } BeanFactoryPostProcessor实在最开始执行的,可以在对象实例化后,有线修改。在Bean被Spring加载后,会生成一个BeanDefinition <bean id="cat" class="org.acy.bfc.Cat" init-method="myInit" destroy-method="myDestroy"> <property name="brand" value="奔驰"/> <property name="color" value="黑色"/> <property name="maxSpeed" value="200"/> </bean> <bean class="org.acy.bfc.MyBeanPostProcessor"/> <bean class="org.acy.bfc.MyBeanFactoryPostProcessor"/> 此处配置了一些Processor,ApplicationContext在启动时候会自动加载这些Processor。 ![]() (编辑:我爱制作网_潮州站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |