31、深入解析spring技术$1

通过前面30章的学习,应该对java的基础及一些jvm底层有了初步了解,接来下将要剖析java最为成功的框架spring;通过剖析整个过程将帮助我们了解jvm底层运作和代码设计风格;

 

先来认识一下spring的缔造者:Rod Johnson; 搞音乐出生的,长的还有点丑,他提出了一个理念:不要滥造车轮子;意思是做车轮子很简单,现在已经有了比较优秀的js封装库像jQuery、nodejs等,而有些三流软件公司放着不用,偏要自己开发一套封装库,让不懂js的人以为这家公司很nb;这句话的另外一个意思:就是造轮子就要造出足够优秀的轮子;

 

他写了几本书:《Expert One-on-One J2EE Design and Development》spring核心思想,他的英文比较烂,一般人不知道他要说什么,估计还没人能翻译成能读的中文;《expert one-on-one J2EE Development without EJB》写了一本书在说EJB的坏话;《Professional Java Development with the spring framework》一看书名就是在给spring做广告;

 

spring有多优秀,那是一个关于春天的故事!

what you will learn from this book?《Professional Java Development with the spring framework》
1、The core inversion of control container(容器) and the concept(概念) of dependency injection(注入);          IoC容器
2、Spring's aspect oriented(面向、定向) programming framework and why aop is important in j2ee development;    AoP框架
3、How to use spring's programmatic(框架) and declarative transaction management services effectively;
4、how to access data using spring's JDBC functionality?
5、Spring services for accessing and implementing EJBs;   spring为EJB提供访问和实现功能
6、Spring's remoting(扩展ing) framework;
spring官网:http://spring.io/

 

先来熟悉几个概念:

1、控制反转:原先一个类A{private String name;} 的属性name需要在实例中为其赋值;比如skx.setName(“skx”);完成这个赋值过程是由  具体的对象实例  完成的;现在就是把这种赋值的权限交给IoC容器,由IoC为实例的属性赋值;比如<bean id="skx" class="org.spring.A"><property name="name"   value="skx"/></bean>就完成了对实例属性的赋值;

2、紧耦合: 比如  A{private B b;}这里A就依赖于属性b,如果属性b的属性和方法发生了变化,极有可能影响到a的功能实现;

      接口解耦:看过25章设计模式之结构模式的外观模式,就会知道如何实现解耦;

3、设计模式的开闭原则:查看27章设计模式之6大原则的开闭原则;

 

spring3.1 

在spring所有功能中,最基础最核心的莫过于IoC了,而IoC容器的具体实现类都是实现BeanFactory这基本接口:

public interface BeanFactory {  	  
	    //这里是对FactoryBean的转义定义,因为如果使用bean的名字检索FactoryBean得到的对象是工厂生成的对象,  
	    //如果需要得到工厂本身,需要转义         
	    String FACTORY_BEAN_PREFIX = "&";    	  
	    //这里根据bean的名字,在IOC容器中得到bean实例,这个IOC容器就是一个大的抽象工厂。  
	    Object getBean(String name) throws BeansException;    
	    //这里根据bean的名字和Class类型来得到bean实例。  
	    Object getBean(String name, Class requiredType) throws BeansException;    
	    //这里提供对bean的检索,看看是否在IOC容器有这个名字的bean  
	    boolean containsBean(String name);    
	    //这里根据bean名字得到bean实例,并同时判断这个bean是不是单例  
	    boolean isSingleton(String name) throws NoSuchBeanDefinitionException; 	  
	    //这里对得到bean实例的Class类型  
	    Class getType(String name) throws NoSuchBeanDefinitionException;   
	    //这里得到bean的别名,如果根据别名检索,那么其原名也会被检索出来  
	    String[] getAliases(String name);    
	}  

 一个Bean 的解析过程非常复杂,功能被分的很细,扩展了很多接口、抽象类和实现类,错综复杂、眼花缭乱,但是最终的实现类有:XmlBeanFactory,ClasspathXmlApplicationContext等等。

实箭头表示继承或实现父类或父接口,虚箭头表示依赖所指向的类或接口;

 BeanFactory下的10个接口:

 从上张图可以看出,ApplicationContext这个接口和最下面的三个接口应该是比较有用的接口;

下面来看下实现类的关系图:XmlBeanFactory主要接口是ConfigurableListableBeanFactory;黄框表示在前面的图中出现,不再向上追溯:

 

XmlBeanFactory声明过时了,来看下面4个现在比较常用的实现bean解析的类:


 
 

这张图中,AbstractApplicationContex、AbstractRefreshableConfigApplicationContextt和4个实现类比较重要;

 

在Spring中,所有的Bean都是有BeanFactory(IoC容器先可以理解为beans.xml)来进行管理的,在BeanFactory中设计了4个getBean方法,通过getBean来获得beans.xml文件中的bean,
返回类型:boolean   方法 :containsBean
返回类型:Object   方法 :getBean
返回类型:T   方法 :getBean
返回类型:T   方法 :getBean
返回类型:Object   方法 :getBean
返回类型:boolean   方法 :isSingleton
返回类型:boolean   方法 :isPrototype
返回类型:boolean   方法 :isTypeMatch
返回类型:Class<?>   方法 :getType
返回类型:String;   方法 :getAliases

 HierarchicalBeanFactory中:

返回类型:boolean   方法 :containsLocalBean
返回类型:BeanFactory   方法 :getParentBeanFactory   //获得BeanFactory

 

 

$1、Resource接口

Spring中,对于资源文件采用一个接口Resource表示。其主要实现类有ClassPathResource、FileSystemResource、UrlResource、ByteArrayResource、ServletContextResource和InputStreamResource。

 

注:ClassPathContextResource是DefaultResourceLoader的内部类

 

 Resource的主要方法:

  • 返回类型:Resource   方法 :createRelative
  • 返回类型:boolean    方法 :isReadable  用于判断对应资源的内容是否可读。需要注意的是当其结果为true的时候,其内容未必真的可读,但如果返回false,则其内容必定不可读。
  • 返回类型:URI       方法 : getURI 
  • 返回类型:URL   方法 :getURL 返回当前资源对应的URL。如果当前资源不能解析为一个URL则会抛出异常。如ByteArrayResource就不能解析为一个URL。
  • 返回类型:String   方法 :getFilename
  • 返回类型:boolean   方法 :exists 用于判断对应的资源是否真的存在。
  • 返回类型:boolean   方法 :isOpen 用于判断当前资源是否代表一个已打开的输入流,如果结果为true,则表示当前资源的输入流不可多次读取,而且在读取以后需要对它进行关闭,以防止内存泄露。该方法主要针对于InputStreamResource,实现类中只有它的返回结果为true,其他都为false。
  • 返回类型:long   方法 :lastModified
  • 返回类型:File   方法 :getFile  返回当前资源对应的File。如果当前资源不能以绝对路径解析为一个File则会抛出异常。如ByteArrayResource就不能解析为一个File。
  • 返回类型:long   方法 :contentLength
  • 返回类型:String   方法 :getDescription

ClassPathResource获取相对路径下的文件,new ClassPathResource(“test.txt”);

SystemResource可用来获取文件系统里面的资源。

UrlResource可用来代表URL对应的资源,它对URL做了一个简单的封装。通过给定一个URL地址,我们就能构建一个UrlResource。

ByteArrayResource是针对于字节数组封装的资源,它的构建需要一个字节数组。

ServletContextResource是针对于ServletContext封装的资源。

InputStreamResource是针对于输入流封装的资源,它的构建需要一个输入流。

getInputStream()是InputStreamSource的唯一声明的抽象方法,返回InputStream;

 

        //将相对地址的 文本文件转为字符流
	public InputStream readRelative(String filePath) throws IOException {  
	      Resource resource = new ClassPathResource(filePath);  
	      String fileName = resource.getFilename();  
	      if (resource.isReadable()) {  
	         InputStream is = resource.getInputStream();  
	         return is;
	      } 
	      return null;
	   }  
	//将绝对地址 的 文本文件转为字符流
	public InputStream readAbsolutely(String filePath) throws IOException {  
		Resource resource = new FileSystemResource(filePath);  
	      if (resource.isReadable()) {  
	    	  InputStream is = resource.getInputStream();    
	    	  return is;
	      }  
	      return null;
      }  
	//将URL地址内容转为字符流,注意转码,百度是utf-8
	public InputStream readURL(String urlPath) throws IOException {  
		urlPath = urlPath.startsWith("http")?urlPath:("http://"+urlPath);
		Resource resource = new UrlResource(urlPath);   
		if (resource.isReadable()) {  
			InputStream is = resource.getInputStream();    
			return is;
		}  
		return null;
	}  
	//将字节内容转为字符流
	public InputStream readByte(byte[] b) throws IOException {  
		Resource resource = new ByteArrayResource(b);   
		if (resource.isReadable()) {  
			InputStream is = resource.getInputStream();    
			return is;
		}  
		return null;
	}  
##########
        //将字符型文件读出,返回一个字符串
	 public  String read(String filename) throws Exception {    
	        BufferedReader br = new BufferedReader(new FileReader(filename));     
	        String s;    
	        StringBuffer sb = new StringBuffer();    
	        while ((s = br.readLine()) != null) {    
	            sb.append(s + "\n");    
	        }    
	        br.close();    
	        return sb.toString();    
	}
	//将字符输入流读出,返回一个字符串
	 public  String read(InputStream  is) throws Exception {    
		 BufferedReader br = new BufferedReader(new InputStreamReader(is));     
		 String s;    
		 StringBuffer sb = new StringBuffer();    
		 while ((s = br.readLine()) != null) {    
			 sb.append(s + "\n");    
		 }    
		 br.close();    
		 return sb.toString();    
	 }

通过上面的几个方法,大致就可以将字符型文件定位,如果不是字符型的文件如何读取呢?参看IO文件复制 

        //将字节文件转换为字节数组
	 public byte[] readB(File file) throws IOException {    
	        BufferedInputStream bf = new BufferedInputStream(new FileInputStream(file));    
	        try {    
	            byte[] data = new byte[bf.available()];    
	            bf.read(data);    
	            return data;    
	        } finally {    
	            bf.close();    
	        }    
	    }    
	 //将字节文件转换为字节数组
	 public byte[] readB(String filePath) throws IOException  {
		 return readB(new File(filePath));
	 }

 字符流文件包括:txt、xml、html等

 二进制文件:图片、音视频、doc、pdf 等

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值