tiny-Spring【1】

Spring框架的兩大特性:IOC、AOPjava

 

1,IOC特性

  IOC:IOC,另一種說法叫DI(Dependency Injection),即依賴注入。它並非一種技術實現,而是一種設計思想spring

  在任何一個有實際開發意義的程序項目中,咱們會使用不少類來描述它們特有的功能,而且經過類與類之間的相互協做來完成特定的業務邏輯。這個時候,每一個類都須要負責管理與本身有交互的類的引用和依賴,代碼將會變的異常難以維護和極度的高耦合。而IOC的出現正是用來解決這個問題,咱們經過IOC將這些相互依賴對象的建立、協調工做交給Spring容器去處理,每一個對象只須要關注其自身的業務邏輯關係就能夠了。在這樣的角度上來看,得到依賴的對象的方式,進行了反轉,變成了由Spring容器控制對象如何獲取外部資源(包括其餘對象和文件資料等等)

編程

大白話就是:安全

咱們在完成一些生產生活勞做【業務邏輯】的時候,須要使用到其餘的工具【其餘實例化對象-如斧頭、鐮刀、馬車等】;在以前咱們都是本身去實例化【自給自足-手動new一個個工具】,效率很低。

到了現代社會【Spring相似框架出現後】,咱們自用關注咱們的工做和生活就好了,其餘的那些工具交給這個現代社會【Spring來進行對象的實例化】去完成。

之前是,咱們主動去new一個工具,如今變成被動的接收工具。你如今不可能本身去造一輛地鐵了吧!直接我要用的話,直接去用就完事了。框架

2,AOP特性

  AOP:面向切面編程,每每被定義爲促使軟件系統實現關注點的分離的技術ide

  系統是由許多不一樣的組件所組成的,每個組件各負責一塊特定功能。除了實現自身核心功能以外,這些組件還常常承擔着額外的職責。例如日誌、事務管理和安全這樣的核心服務常常融入到自身具備核心業務邏輯的組件中去。這些系統服務常常被稱爲橫切關注點,由於它們會跨越系統的多個組件。工具

通知: 通知定義了切面是什麼以及什麼時候使用的概念。Spring 切面能夠應用5種類型的通知:測試

  •   前置通知(Before):在目標方法被調用以前調用通知功能。
  •   後置通知(After):在目標方法完成以後調用通知,此時不會關心方法的輸出是什麼。
  •   返回通知(After-returning):在目標方法成功執行以後調用通知。
  •   異常通知(After-throwing):在目標方法拋出異常後調用通知。
  •   環繞通知(Around):通知包裹了被通知的方法,在被通知的方法調用以前和調用以後執行自定義的行爲。

鏈接點:是在應用執行過程當中可以插入切面的一個點。this

切點: 切點定義了切面在何處要織入的一個或者多個鏈接點。
切面:是通知和切點的結合。通知和切點共同定義了切面的所有內容。
引入:引入容許咱們向現有類添加新方法或屬性。
織入:是把切面應用到目標對象,並建立新的代理對象的過程。切面在指定的鏈接點被織入到目標對象中。在目標對象的生命週期中有多個點能夠進行織入:
編譯期: 在目標類編譯時,切面被織入。這種方式須要特殊的編譯器。AspectJ的織入編譯器就是以這種方式織入切面的。
類加載期:切面在目標加載到JVM時被織入。這種方式須要特殊的類加載器(class loader)它能夠在目標類被引入應用以前加強該目標類的字節碼。
運行期: 切面在應用運行到某個時刻時被織入。通常狀況下,在織入切面時,AOP容器會爲目標對象動態地建立一個代理對象。SpringAOP就是以這種方式織入切面的。

spa

3,tiny-Spring

參考-黃億華的tiny-Spring

3.1 Step1

BeanFactory.java工廠模式接口
package com.cnblogs.Factory;

public interface BeanFactory {
    /**
     * 工廠模式中的接口,用於產生實體類
     * @param name
     * @return
     * @throws Exception
     */
    Object getBean(String name) throws Exception;
}

 

AbstractBeanFactory.java註冊表類型【登記已經有的實例】
package com.cnblogs.Factory;

import com.cnblogs.bean.BeanDefinition;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class AbstractBeanFactory implements BeanFactory {
    private Map<String, BeanDefinition> beanDefinitionMap=new ConcurrentHashMap<String, BeanDefinition>();//線程安全-散列表
    private final List<String> beanDefinitionNames=new ArrayList<String>();//實體對象名稱

    @Override
    public Object getBean(String name) throws Exception {
        BeanDefinition beanDefinition=beanDefinitionMap.get(name);
        if(beanDefinition==null){
            throw new IllegalArgumentException("No bean named"+name+" is defined");
        }
        Object bean=beanDefinition.getBean(name);
        return bean;
    }

    //本質上就是進行名稱和對象的映射到散列表上
    public void registerBeanDefinition(String name,BeanDefinition beanDefinition) throws Exception{
        beanDefinitionMap.put(name,beanDefinition);
        beanDefinitionNames.add(name);
    }
}

 

BeanDefinition.java 傳入實例【相似包裝盒的做用-裏面的東西能夠千差萬別】
package com.cnblogs.bean;


/**
 * bean的內容及元數據,保存在BeanFactory中,包裝bean的實體
 */

public class BeanDefinition {
    private Object bean;
    private Class<?> beanClass;
    private String  beanClassName;
    public BeanDefinition(){}
    public BeanDefinition(Object object){
        this.bean=object;
    }

    public void setBeanClassName(String beanClassName) throws ClassNotFoundException {
        this.beanClassName=beanClassName;
        try{
            this.beanClass=Class.forName(beanClassName);
        }catch(ClassNotFoundException e){
            e.printStackTrace();
        }
    }

}

 

Client.java測試類
import com.cnblogs.Factory.AbstractBeanFactory;
import com.cnblogs.Factory.BeanFactory;
import com.cnblogs.bean.BeanDefinition;

class HelloWorldServiceImpl {

    public void helloWorld2() {
        System.out.println("hello");
    }
}

public class Client {
    public static void Step1() throws Exception{
        BeanFactory beanFactory=new AbstractBeanFactory();
        BeanDefinition beanDefinition=new BeanDefinition(new HelloWorldServiceImpl());

        ((AbstractBeanFactory)beanFactory).registerBeanDefinition("helloworld",beanDefinition);

        HelloWorldServiceImpl h=(HelloWorldServiceImpl) beanFactory.getBean("helloworld");
        h.helloWorld2();
    }


    public static void main(String[] args) throws Exception {
        Client.Step1();
    }
}
View Code
 

3.2 Step2【利用反射機制傳入String 類名-實例化對象】

 

    public static void Step2() throws Exception{
        BeanFactory beanFactory=new AbstractBeanFactory();//無參構造,不傳入實例
        BeanDefinition beanDefinition=new BeanDefinition();
        beanDefinition.setBeanClassName("com.spring.step1.test.HelloWorldServiceImpl");

        ((AbstractBeanFactory) beanFactory).registerBeanDefinition("helloworld",beanDefinition);

        HelloWorldServiceImpl h=(HelloWorldServiceImpl) beanFactory.getBean("helloworld");
        h.helloWorld2();
    }

AbstractBeanFactory/getBean()方法

    @Override
    public Object getBean(String name) throws Exception {
        BeanDefinition beanDefinition=beanDefinitionMap.get(name);
        if(beanDefinition==null){
            throw new IllegalArgumentException("No bean named "+name+" is defined");
        }
        Object bean=beanDefinition.getBean();
        if (bean==null) {
            Constructor constructor=beanDefinition.getBeanClass().getDeclaredConstructor();
            constructor.setAccessible(true);//設置權限
            bean=constructor.newInstance();
            beanDefinition.setBean(bean);
        }
        return bean;
    }

 

3.3 step3【注入參數】

以前的實體類HelloWorldServiceImpl中有屬性後

private String text;
private int a;

HelloWorldServiceImpl實體類
class HelloWorldServiceImpl {
    private String text;
    private int a;

    public HelloWorldServiceImpl(){}

    public void helloWorld2(){
        System.out.println("hello");
    }

    public void helloWorld3() {
        System.out.println(text + a + " ss");
    }
}
PropertyValue封裝類
package com.spring.step1.bean;

/**
 * 用於bean的屬性注入
 * 和BeanDefinition一個效果,將實體進行封裝到一個動態類中
 */
public class PropertyValue {
    private final String name;
    private final Object value;  //    省略get/set  後文對簡單的get/set方法將直接省略 再也不說明

    public PropertyValue(String name, Object value) {
        this.name = name;
        this.value = value;
    }

    public String getName() {
        return name;
    }

    public Object getValue() {
        return value;
    }
}
PropertyValues封裝類
package com.spring.step1.bean;

import java.util.ArrayList;
import java.util.List;

/**
 * 包裝一個對象全部的PropertyValue。<br/>
 * 爲何封裝而不是直接用List?由於能夠封裝一些操做。
 * 單純的一個ArrayList對象,其中封裝了一些實體對象
 */
public class PropertyValues {
    private final List<PropertyValue> propertyValueList = new ArrayList<PropertyValue>();
    public PropertyValues(){}

    public void addPropertyValue(PropertyValue pv){
        //TODO:這裏能夠對於重複propertyName進行判斷,直接用list無法作到
        //    System.out.println(pv.getName()+pv.getValue());
        this.propertyValueList.add(pv);
    }
    public List<PropertyValue> getPropertyValues() {
        return this.propertyValueList;
    }
}

在BeanDefinition里加入【private PropertyValues propertyValues;】setter和getter默認

AbstractBeanFactory類中的getBean也要進行相關修改
    @Override
    public Object getBean(String name) throws Exception {
        BeanDefinition beanDefinition=beanDefinitionMap.get(name);
        if(beanDefinition==null){
            throw new IllegalArgumentException("No bean named "+name+" is defined");
        }

        Object bean=beanDefinition.getBean();
        if (bean==null) {
            Constructor constructor=beanDefinition.getBeanClass().getDeclaredConstructor();
            constructor.setAccessible(true);//設置權限
            bean=constructor.newInstance();
            constructor.setAccessible(false);//設置權限
            beanDefinition.setBean(bean);
        }
        creatBean(bean, beanDefinition);
        return bean;
    }

    public void creatBean(Object bean, BeanDefinition beanDefinition) throws Exception{
        if(beanDefinition.getPropertyValues() != null)
            creatBeanWithProperty(bean, beanDefinition);
    }

    public void creatBeanWithProperty(Object bean, BeanDefinition beanDefinition) throws Exception{
        int size =beanDefinition.getPropertyValues().getPropertyValues().size();//List長度
        List<PropertyValue> list = beanDefinition.getPropertyValues().getPropertyValues();//由外及內
        for (int i = 0; i <size ; i++) {
            if(list.get(i).getValue() instanceof BeanReference) {
                String beanName = ((BeanReference) list.get(i).getValue()).getName();
                Object referenceBean = getBean(beanName);
                String ms = "set" + Character.toUpperCase(list.get(i).getName().charAt(0)) + list.get(i).getName().substring(1);
                Method m = bean.getClass().getDeclaredMethod(ms, referenceBean.getClass());//反射機制的數據配置-初始化處理
                m.invoke(bean, referenceBean);
            }else {//手動進行賦值
                String fieldName = list.get(i).getName();
                Object value = list.get(i).getValue();
                Field field = bean.getClass().getDeclaredField(fieldName); // getDeclaredField是得到全部的字段(不只僅是public)
                field.setAccessible(true); // 這一步必須有
                field.set(bean, value);
                field.setAccessible(false); // 這一步必須有
            }
        }
    }

測試類step3

    public static void Step3() throws Exception {
        // 1.初始化beanfactory
        BeanFactory beanFactory = new AbstractBeanFactory();
        // 2.bean定義
        BeanDefinition beanDefinition = new BeanDefinition();
        beanDefinition.setBeanClassName("com.spring.step1.test.HelloWorldServiceImpl");
        // 3.設置屬性
        PropertyValues propertyValues = new PropertyValues();
        propertyValues.addPropertyValue(new PropertyValue("text","Hello World!"));
        propertyValues.addPropertyValue(new PropertyValue("a",new Integer(15)));
        beanDefinition.setPropertyValues(propertyValues);
        // 4.註冊bean
        ((AbstractBeanFactory)beanFactory).registerBeanDefinition("helloworld", beanDefinition);

        HelloWorldServiceImpl h = (HelloWorldServiceImpl) beanFactory.getBean("helloworld");
        h.helloWorld3();
    }

3.4 step4【加入引用變量】

引用實體類

package com.spring.step1.test;

public class OutputService {
    public static void output(String text){
        System.out.println(text);
    }
}

加入引用變量

 

 

 

 

 

參考連接:

http://www.javashuo.com/article/p-bsstwobq-dn.html【這個講的很清楚啊,舉得例子和現實很貼切】

https://blog.csdn.net/dlf123321/article/details/39994071

相關文章
相關標籤/搜索