<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Spring源碼分析

      01、Spring源碼分析:initPropertySources方法擴展點

      Spring的強大之處不僅僅在于它為Java開發者提供了極大便利,更在于它的開放式架構,使得用戶可以擁有最大擴展Spring的能力。

      protected void initPropertySources() {
      		// For subclasses: do nothing by default.
      	}
      

      在AbstractApplicationContext類中有一個initPropertySources方法是留給子類擴展,它是在refresh()的第一個方法prepareRefresh();方法中調用。

      protected void prepareRefresh() {
      
      
      		// Switch to active.
      		// 設置容器啟動的時間
      		this.startupDate = System.currentTimeMillis();
      		// 容器的關閉標志位
      		this.closed.set(false);
      		// 容器的激活標志位
      		this.active.set(true);
      
      		// 記錄日志
      		if (logger.isDebugEnabled()) {
      
      
      			if (logger.isTraceEnabled()) {
      
      
      				logger.trace("Refreshing " + this);
      			}
      			else {
      
      
      				logger.debug("Refreshing " + getDisplayName());
      			}
      		}
      
      		// Initialize any placeholder property sources in the context environment.
      		// 留給子類覆蓋,初始化屬性資源
      		initPropertySources();
      
      		// Validate that all properties marked as required are resolvable:
      		// see ConfigurablePropertyResolver#setRequiredProperties
      		// 創建并獲取環境對象,驗證需要的屬性文件是否都已經放入環境中
      		getEnvironment().validateRequiredProperties();
      
      		// Store pre-refresh ApplicationListeners...
      		// 判斷刷新前的應用程序監聽器集合是否為空,如果為空,則將監聽器添加到此集合中
      		if (this.earlyApplicationListeners == null) {
      
      
      			this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
      		}
      		else {
      
      
      			// Reset local application listeners to pre-refresh state.
      			// 如果不等于空,則清空集合元素對象
      			this.applicationListeners.clear();
      			this.applicationListeners.addAll(this.earlyApplicationListeners);
      		}
      
      		// Allow for the collection of early ApplicationEvents,
      		// to be published once the multicaster is available...
      		// 創建刷新前的監聽事件集合
      		this.earlyApplicationEvents = new LinkedHashSet<>();
      	}
      

      所以我們可以繼承此類或其子類來重寫initPropertySources方法,實現一些擴展。

      public class MyClassPathXmlApplicationContext extends ClassPathXmlApplicationContext {
      	public MyClassPathXmlApplicationContext(String... configLocations){
      		super(configLocations);
      	}
      
      	@Override
      	protected void initPropertySources() {
      		System.out.println("擴展initPropertySource");
      		//這里添加了一個name屬性到Environment里面,以方便我們在后面用到
      		getEnvironment().getSystemProperties().put("name","bobo");
      		//這里要求Environment中必須包含username屬性,如果不包含,則拋出異常
      		getEnvironment().setRequiredProperties("username");
      	}
      }
      

      此處我們做了兩個擴展:
      第一,向Environment中添加了一個屬性值。
      第二:我們設置了一個必要的系統屬性username,當Environment中不包含username屬性時系統會拋出異常。

      測試類:

      public class Test {
      
      	public static void main(String[] args) {
      		MyClassPathXmlApplicationContext ac = new MyClassPathXmlApplicationContext("applicationContext.xml");
      
      //        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-${username}.xml");
      	}
      }
      

      當然你也可以做其它擴展,這里只是列舉了一個例子。

      02、Spring源碼分析:customizeBeanFactory方法擴展點

      Spring的強大之處不僅僅在于它為Java開發者提供了極大便利,更在于它的開放式架構,使得用戶可以擁有最大擴展Spring的能力。

      protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
      
      
      		// 如果屬性allowBeanDefinitionOverriding不為空,設置給beanFactory對象相應屬性,是否允許覆蓋同名稱的不同定義的對象
      		if (this.allowBeanDefinitionOverriding != null) {
      
      
      			beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
      		}
      		// 如果屬性allowCircularReferences不為空,設置給beanFactory對象相應屬性,是否允許bean之間存在循環依賴
      		if (this.allowCircularReferences != null) {
      
      
      			beanFactory.setAllowCircularReferences(this.allowCircularReferences);
      		}
      	}
      

      在AbstractRefreshableApplicationContext類中有一個customizeBeanFactory方法是留給子類擴展,它是在refresh()的第二個方法obtainFreshBeanFactory()–>refreshBeanFactory()方法中調用。

      protected final void refreshBeanFactory() throws BeansException {
      
      
      		// 如果存在beanFactory,則銷毀beanFactory
      		if (hasBeanFactory()) {
      
      
      			destroyBeans();
      			closeBeanFactory();
      		}
      		try {
      
      
      			// 創建DefaultListableBeanFactory對象
      			DefaultListableBeanFactory beanFactory = createBeanFactory();
      			// 為了序列化指定id,可以從id反序列化到beanFactory對象
      			beanFactory.setSerializationId(getId());
      			// 定制beanFactory,設置相關屬性,包括是否允許覆蓋同名稱的不同定義的對象以及循環依賴
      			customizeBeanFactory(beanFactory);
      			// 初始化documentReader,并進行XML文件讀取及解析,默認命名空間的解析,自定義標簽的解析
      			loadBeanDefinitions(beanFactory);
      			this.beanFactory = beanFactory;
      		}
      		catch (IOException ex) {
      
      
      			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
      		}
      	}
      

      此方法是用來實現BeanFactory的屬性設置,主要是設置兩個屬性:

      • allowBeanDefinitionOverriding:是否允許覆蓋同名稱的不同定義的對象。
      • allowCircularReferences:是否允許bean之間的循環依賴。

      如下例子:

      public class MyClassPathXmlApplicationContext extends ClassPathXmlApplicationContext {
      
      
      	public MyClassPathXmlApplicationContext(String... configLocations){
      
      
      		super(configLocations);
      	}
      
      	@Override
      	protected void initPropertySources() {
      
      
      		System.out.println("擴展initPropertySource");
      		//這里添加了一個name屬性到Environment里面,以方便我們在后面用到
      		getEnvironment().getSystemProperties().put("name","bobo");
      		//這里要求Environment中必須包含username屬性,如果不包含,則拋出異常
      		getEnvironment().setRequiredProperties("username");
      	}
      
      	@Override
      	protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
      
      
      		super.setAllowBeanDefinitionOverriding(false);
      		super.setAllowCircularReferences(false);
      		super.customizeBeanFactory(beanFactory);
      	}
      

      public class Test {
      
      
      
      	public static void main(String[] args) {
      
      
      		MyClassPathXmlApplicationContext ac = new MyClassPathXmlApplicationContext("applicationContext.xml");
      
      //        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-${username}.xml");
      	}
      }
      
      
      }
      

      03、Spring源碼分析:自定義配置文件標簽

      Spring的強大之處不僅僅在于它為Java開發者提供了極大便利,更在于它的開放式架構,使得用戶可以擁有最大擴展Spring的能力。

      我們在用xml定義spring信息時,默認的element只包含beans,bean,import,alias這四個,其它任何標簽都屬于自定義標簽,均需要引入相應的命名空間,如:context,aop標簽等。

      protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
      
      
      		if (delegate.isDefaultNamespace(root)) {
      
      
      			NodeList nl = root.getChildNodes();
      			for (int i = 0; i < nl.getLength(); i++) {
      
      
      				Node node = nl.item(i);
      				if (node instanceof Element) {
      
      
      					Element ele = (Element) node;
      					if (delegate.isDefaultNamespace(ele)) {
      
      
      						//處理默認的標簽元素
      						parseDefaultElement(ele, delegate);
      					}
      					else {
      
      
      						//處理自定義的標簽元素
      						delegate.parseCustomElement(ele);
      					}
      				}
      			}
      		}
      		else {
      
      
      			delegate.parseCustomElement(root);
      		}
      	}
      

      對應的源碼處理在DefaultBeanDefinitionDocumentReader類的parseBeanDefinitions方法里面。

      自定義標簽元素

      1,定義People.java

      public class People {
      
      
      	private String id;
      	private int age;
      	private String name;
      	private String address;
      
      	public People(String id, int age, String name, String address) {
      
      
      		this.id = id;
      		this.age = age;
      		this.name = name;
      		this.address = address;
      	}
      
      	public People() {
      
      
      	}
      
      	public String getId() {
      
      
      		return id;
      	}
      
      	public void setId(String id) {
      
      
      		this.id = id;
      	}
      
      	public int getAge() {
      
      
      		return age;
      	}
      
      	public void setAge(int age) {
      
      
      		this.age = age;
      	}
      
      	public String getName() {
      
      
      		return name;
      	}
      
      	public void setName(String name) {
      
      
      		this.name = name;
      	}
      
      	public String getAddress() {
      
      
      		return address;
      	}
      
      	public void setAddress(String address) {
      
      
      		this.address = address;
      	}
      
      	@Override
      	public String toString() {
      
      
      		return "People{" +
      				"id='" + id + '\'' +
      				", age=" + age +
      				", name='" + name + '\'' +
      				", address='" + address + '\'' +
      				'}';
      	}
      }
      

      2,在resources/META-INF目錄下定義people.xsd,spring.handlers,spring.schemas文件

      people.xsd
      <?xml version="1.0" encoding="UTF-8"?>
      <schema xmlns="http://www.w3.org/2001/XMLSchema"
      		targetNamespace="http://www.bobo.com/schema/people"
      		xmlns:tns="http://www.bobo.com/schema/people"
      		elementFormDefault="qualified">
      	<element name="people">
      		<complexType>
      			<attribute name ="id" type = "string"/>
      			<attribute name ="age" type = "int"/>
      			<attribute name ="name" type = "string"/>
      			<attribute name ="address" type = "string"/>
      		</complexType>
      	</element>
      </schema>
      
      spring.handlers
      http\://www.bobo.com/schema/people=com.bobo.custom.PeopleNamespaceHandler
      
      spring.schemas
      http\://www.bobo.com/schema/people.xsd=META-INF/people.xsd
      

      3,創建對應的namespaceHandler類PeopleNamespaceHandler.java

      package com.wsj.custom;
      
      import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
      
      /**
       * @author wsj
       * @date 2024-04-20
       */
      
      public class PeopleNamespaceHandler extends NamespaceHandlerSupport {
      
      
      	@Override
      	public void init() {
      
      
      		super.registerBeanDefinitionParser("people",new PeopleBeanDefinitionParser());
      	}
      }
      

      4,創建對應的BeanDefinitionParser類PeopleBeanDefinitionParser.java

      package com.wsj.custom;
      
      import org.springframework.beans.factory.support.BeanDefinitionBuilder;
      import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
      import org.springframework.util.StringUtils;
      import org.w3c.dom.Element;
      
      /**
       * @author wsj
       * @date 2024-04-20
       */
      
      public class PeopleBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
      
      
      	@Override
      	protected Class<?> getBeanClass(Element element) {
      
      
      		return People.class;
      	}
      
      	@Override
      	protected void doParse(Element element, BeanDefinitionBuilder builder) {
      
      
      		String id = element.getAttribute("id");
      		String age = element.getAttribute("age");
      		String name = element.getAttribute("name");
      		String address = element.getAttribute("address");
      		if (StringUtils.hasLength(id)){
      
      
      			builder.addPropertyValue("id",id);
      		}
      		if (StringUtils.hasLength(age)){
      
      
      			builder.addPropertyValue("age",age);
      		}
      		if (StringUtils.hasLength(name)){
      
      
      			builder.addPropertyValue("name",name);
      		}
      		if (StringUtils.hasLength(address)){
      
      
      			builder.addPropertyValue("address",address);
      		}
      	}
      }
      

      5,創建application-context.xml配置文件

      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
      	   xmlns:bo="http://www.bobo.com/schema/people"
      	   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
      			http://www.bobo.com/schema/people http://www.bobo.com/schema/people.xsd">
      
      	<bo:people id="wsj" age="20" name="wsjxtt" address="廣東省深圳市"></bo:people>
      
      </beans>
      

      6,創建測試類

      package com.wsj;
      
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      
      public class Test {
      
      
      
      	public static void main(String[] args) {
      
      
      		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");
      		System.out.println(context.getBean("wsj"));
      	}
      }
      

      運行輸出

      People{
      
      	 id='wsj', age=20, name='wsjxtt', address='廣東省深圳市'}
      
      posted @ 2024-07-14 21:44  二價亞鐵  閱讀(226)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 日韩在线视频一区二区三| 欧美视频网站www色| 一区二区亚洲人妻精品| 丝袜老师办公室里做好紧好爽| 性欧美牲交在线视频| 少妇高潮水多太爽了动态图| 日韩内射美女人妻一区二区三区| 亚洲熟妇自偷自拍另类| 国产成AV人片久青草影院| 国产日韩AV免费无码一区二区三区| 亚洲精品国产精品国在线| 国产成人av电影在线观看第一页| 欧洲码亚洲码的区别入口| 国产精品无码av不卡| 亚洲国产区男人本色vr| 呻吟国产av久久一区二区| 在线视频一区二区三区色| 丁香婷婷在线视频| 察隅县| аⅴ天堂国产最新版在线中文| 亚洲精品色哟哟一区二区| 国产视色精品亚洲一区二区| japanese边做边乳喷| 亚洲中文字幕无码久久2017| 青春草公开在线视频日韩| 湘潭县| 重口SM一区二区三区视频| 樱桃视频影院在线播放| 十四以下岁毛片带血a级| 高清中文字幕国产精品| 亚洲欧美日韩愉拍自拍美利坚| 视频一区二区不中文字幕| 国产中文字幕在线一区| 一区二区中文字幕av| 亚洲www永久成人网站| 国产黄色一区二区三区四区| 精品中文字幕一区在线| 亚洲午夜亚洲精品国产成人| 色综合久久综合中文综合网| 国产日韩欧美亚洲精品95| 国产AV影片麻豆精品传媒|