1. 程式人生 > >Spring 中的接口知識整理

Spring 中的接口知識整理

height 檢查 factory read system 是否 ID user cati

本想每個小知識一篇隨筆,但是那樣,看起來有些單薄,所以,就放在一片文章裏了。而且,以後還會慢慢在最後不斷的追加。

目錄:

FactoryBean

BeanPostProcessor

1.FactoryBean

FactoryBean接口,它在Spring框架源碼內部,被大量使用,如使用AOP創建bean的代理時,使用了ProxyFactoryBean;從JNDI中查找對象時,使用了JndiObjectFactoryBean。

它在框架外,很少使用。但是為了學習,也得研究研究,您說是不?

它怎麽使用?首先看看構造。

1 public interface FactoryBean<T> {

 // 返回的是這個工廠管理的對象的實例
2 T getObject() throws Exception; 3
 // 返回的是工廠創建的對象的類型 4 Class<?> getObjectType(); 5 6 boolean isSingleton(); 7 8 }

上個例子,看具體東西。

 1 public class Tool {
 2 
 3 
 4     private int id;
 5     public Tool(int id) {
 6         this.id = id;
 7     }
 8     public int getId() {
 9         return id;
10 } 11 12 public void setId(int id) { 13 this.id = id; 14 } 15 }
 1 public class ToolFactory implements FactoryBean<Tool> {
 2 
 3     private int factoryId;
 4     private int toolId;
 5 
    // 創建的是Tool的對象 6 @Override 7 public Tool getObject() throws Exception { 8 return new Tool(toolId); 9 }
10 11 @Override 12 public Class<?> getObjectType() { 13 return Tool.class; 14 } 15 16 @Override 17 public boolean isSingleton() { 18 return false; 19 } 20 21 public int getFactoryId() { 22 return factoryId; 23 } 24 25 public int getToolId() { 26 return toolId; 27 } 28 29 public void setFactoryId(int factoryId) { 30 this.factoryId = factoryId; 31 } 32 33 public void setToolId(int toolId) { 34 this.toolId = toolId; 35 } 36 37 }
 1 public class Test {
 2 
 3     public static void main(String[] args) {  
 4         @SuppressWarnings("resource")
 5         ApplicationContext context = new ClassPathXmlApplicationContext("beaFactoryTest.xml");  
 6         Tool tool = (Tool) context.getBean("tool");  
       // 在名字前面加 & 表示要得到工廠類的bean
7 ToolFactory tool2 = (ToolFactory) context.getBean("&tool"); 8 System.out.println("Tool Id is " + tool.getId()); 9 System.out.println("ToolFactory Id is " + tool2.getFactoryId()); 10 11 } 12 }
1     <bean id="tool" class="com.lee.demo.beanfactory.ToolFactory">
2         <property name="factoryId" value="9090"/>
3         <property name="toolId" value="108"/>
4     </bean>

最後執行結果:

Tool Id is 108
ToolFactory Id is 9090

2.BeanPostProcessor

它叫bean後處理器,也就是處理bean,它針對所有的bean,在初始化前後,對bean進行操作。主要內容我會在例子中描述。

例子:

 1 public class HelloWorld {
 2     private String message;
 3 
 4     public void setMessage(String message) {
 5         this.message = message;
 6     }
 7 
 8     public void getMessage() {
 9         System.out.println("Your Message : " + message);
10     }
11   

// 加上init方法和destory方法,是為了在後面驗證他們和postProcessBeforeInitialization postProcessAfterInitialization 執行的先後順序 12 public void init() { 13 System.out.println("Bean is going through init."); 14 } 15 16 public void destroy() { 17 System.out.println("Bean will destroy now."); 18 } 19 }

 1 public class InitHelloWorld implements BeanPostProcessor {
 2 
    // BeanPostProcessor 接口中主要是下面兩個方法 初始化前的後處理 初始化後的後處理 3 @Override 4 public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 5 6 System.out.println("BeforeInitialization : " + beanName); 7 return bean; // you can return any other object as well 8 } 9 10 @Override 11 public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 12 13 System.out.println("AfterInitialization : " + beanName); 14 return bean; // you can return any other object as well 15 } 16 17 }
Test.java
 1 public class Test {
 2 
 3     public static void main(String[] args) {  
 4         @SuppressWarnings("resource")
 5         AbstractApplicationContext  context = new ClassPathXmlApplicationContext("beaFactoryTest.xml");  
 6         HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
 7         obj.getMessage();
       // 註冊鉤子方法
8 context.registerShutdownHook(); 9 } 10 }

查看源碼:

 1 @Override
    // 在JVM運行期間,註冊一個鉤子關閉方法,關閉掉這個context。實際的關閉程序的操作,被代理給doClose方法。
2 public void registerShutdownHook() { 3 if (this.shutdownHook == null) { 4 // No shutdown hook registered yet. 5 this.shutdownHook = new Thread() { 6 @Override 7 public void run() { 8 doClose(); 9 } 10 }; 11 Runtime.getRuntime().addShutdownHook(this.shutdownHook); 12 } 13 }

xml文件

1     <bean id = "helloWorld" class = "com.lee.demo.beanfactory.HelloWorld"
2       init-method = "init" destroy-method = "destroy">
3       <property name = "message" value = "Hello World!"/>
4    </bean>
5 
6    <bean class = "com.lee.demo.beanfactory.InitHelloWorld" />

執行結果:

1 BeforeInitialization : helloWorld
2 Bean is going through init.
3 AfterInitialization : helloWorld
4 Your Message : Hello World!
5 [org.springframework.context.support.ClassPathXmlApplicationContext] - Closing org.springframework.context.support.ClassPathXmlApplicationContext@6ae40994: startup date [Thu May 17 23:31:53 JST 2018]; root of context hierarchy
6 Bean will destroy now.

在這裏大致說一下Spring的實例化過程:

實例化Bean對象→設置對象屬性→檢查Aware相關接口並設置相關依賴→BeanPostProcessor前置處理→檢查是否是InitializingBean以決定是否調用afterPropertiesSet方法→

檢查是否配置有自定義的init-method方法→BeanPostProcessor後置處理→是否實現DisposableBean接口→是否配置有自定義的destroy方法

3.Aware接口

它是幹什麽用的呢?作用就是通過上下文(Context)可以獲得當前環境。看看它的接口:

技術分享圖片

我們拿BeanNameAware來舉個例子。

 1 public class User implements GetNameAware {
 2 
 3     private String id;
 4     private String name;
 5     private String address;
 6     @Override
 7     public void setBeanName(String name) {
 8         this.id = name;
 9     }
10     public String getId() {
11         return id;
12     }
13     public String getName() {
14         return name;
15     }
16     public String getAddress() {
17         return address;
18     }
19     public void setId(String id) {
20         this.id = id;
21     }
22     public void setName(String name) {
23         this.name = name;
24     }
25     public void setAddress(String address) {
26         this.address = address;
27     }
28 
29 }
 1 public class User2 {
 2 
 3     private String id;
 4     private String name;
 5     private String address;
 6     public String getId() {
 7         return id;
 8     }
 9     public String getName() {
10         return name;
11     }
12     public String getAddress() {
13         return address;
14     }
15     public void setId(String id) {
16         this.id = id;
17     }
18     public void setName(String name) {
19         this.name = name;
20     }
21     public void setAddress(String address) {
22         this.address = address;
23     }
24 
25 }
1 public interface GetNameAware extends BeanNameAware {
2 
3 
4 }
 1 public class Test {
 2     public static void main(String[] args) {  
 3         ApplicationContext ctx = new ClassPathXmlApplicationContext("beaFactoryTest.xml");
 4         User user = (User) ctx.getBean("user1");
 5         User2 user2 = (User2) ctx.getBean("user2");
 6         System.out.println("user id " + user.getId() + " user name " + user.getName() + " user address " + user.getAddress());
 7         System.out.println("========================================");
 8         System.out.println("user2 id " + user2.getId() + " user2 name " + user2.getName() + " user2 address " + user2.getAddress());
 9     }
10 }
1     <bean id="user1" class="com.lee.demo.aware.User">
2         <property name="name" value="lee"/>
3         <property name="address" value="China"/>
4     </bean>
5     
6     <bean id="user2" class="com.lee.demo.aware.User2">
7         <property name="name" value="lin"/>
8         <property name="address" value="Tokyo"/>
9     </bean>

執行結果(user id 因為繼承了GetNameAware接口,對BeanName進行了設置):

1 user id user1 user name lee user address China
2 ========================================
3 user2 id null user2 name lin user2 address Tokyo




Spring 中的接口知識整理