JavaWeb study notes (21) to realize his Spring IOC and AOP

This time has been learning the Spring framework for IOC and AOP only understand the principle, in order to deepen understanding, reference Tian Xiaobo this blog to achieve the basic functions of IOC and AOP.

A. IOC simple implementation

1. The implementation process

  1. Load xml configuration file, which traverse the label
  2. Get tag id and class attributes, class attribute corresponding class loading and reflection created using bean.
  3. Traversing element tag, getting a property value and attribute values ​​into the bean filled.
  4. The bean registered to the bean container.

2. implementation code

  1. SimpleIOC class, ioc major implementation class
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Time
 * @created 2019/7/2
 */
public class SimpleIOC {
    // 用来存放bean的容器
    private Map<String , Object> beanMap = new HashMap<>();

    public SimpleIOC(String location) throws Exception{
        loadBeans(location);
    }
    // 获取bean
    public Object getBean(String name){
        System.out.println(beanMap);
        Object bean = beanMap.get(name);
        if( bean == null){
            throw  new IllegalArgumentException("there is no bean with name" + name);
        }
        return bean;
    }
    private void loadBeans(String location) throws Exception{
        // 加载xml配置文件
        InputStream inputStream = new FileInputStream(location);
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = factory.newDocumentBuilder();
        Document doc = docBuilder.parse(inputStream);
        Element root = doc.getDocumentElement();
        NodeList nodes = root.getChildNodes();

        // 遍历bean 标签
        for(int i = 0; i < nodes.getLength(); i++) {
            Node node = nodes.item(i);
            if (node instanceof Element) {
                Element ele = (Element) node;
                String id = ele.getAttribute("id");
                String className = ele.getAttribute("class");

                // 加载beanclass
                Class beanClass = null;
                try {
                    beanClass = Class.forName(className);
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                    return;
                }

                // 创建bean
                Object bean = beanClass.newInstance();
                // 遍历 property 标签
                NodeList propertyNodes = ele.getElementsByTagName("property");
                for (int j = 0; j < propertyNodes.getLength(); j++) {
                    Node propertyNode = propertyNodes.item(j);
                    if (propertyNode instanceof Element) {
                        Element propertyElement = (Element) propertyNode;
                        String name = propertyElement.getAttribute("name");
                        String value = propertyElement.getAttribute("value");

                        //利用反射将bean 相关字段访问权限设为可访问
                        Field declaredField = bean.getClass().getDeclaredField(name);
                        declaredField.setAccessible(true);
                        if (value != null && value.length() > 0) {
                            // 将属性填充到字段中
                            declaredField.set(bean, value);
                        } else {
                            String ref = propertyElement.getAttribute("ref");
                            if (ref == null || ref.length() == 0) {
                                throw new IllegalArgumentException("ref config error");
                            }
                            // 将引用填充到相关字段中
                            declaredField.set(bean, getBean(ref));
                        }
                        registerBean(id , bean);
                    }
                }
            }
        }
    }
    private void registerBean(String id, Object bean){
        beanMap.put(id, bean);
    }
}

The code is relatively simple, by parsing dom way to obtain the content xml configuration file, and then create an instance, the injection parameters. Sign up to the bean container.

  1. Injection type
    used for detecting whether the IOC container successful class

Wheell class

package test;

/**
 * @author Time
 * @created 2019/7/2
 */
public class Wheel {
    private String brand;
    private String specification;

    @Override
    public String toString() {
        return "Wheel{" +
                "brand='" + brand + '\'' +
                ", specification='" + specification + '\'' +
                '}';
    }
}

Car category

package test;

/**
 * @author Time
 * @created 2019/7/2
 */
public class Wheel {
    private String brand;
    private String specification;

    @Override
    public String toString() {
        return "Wheel{" +
                "brand='" + brand + '\'' +
                ", specification='" + specification + '\'' +
                '}';
    }
}

  1. xml configuration file
<beans>
    <bean id = "wheel" class="test.Wheel">
        <property  name="brand" value="Michelin"/>
        <property  name="specification" value="256/60 R18"/>
    </bean>
    <bean id="car" class="test.Car">
        <property name="name" value="Mercedes Benz G 500"/>
        <property name="length" value="4717mm"/>
        <property name="width" value="1855mm"/>
        <property name="height" value="1949mm"/>
        <property name="wheel" ref="wheel"/>
    </bean>
</beans>
  1. Test category

Verify successful

/**
 * @author Time
 * @created 2019/7/2
 */
import test.*;
public class test {
    public static void main(String[] args) throws Exception {
        String location = SimpleIOC.class.getClassLoader().getResource("ioc.xml").getFile();
        System.out.println(location);
        SimpleIOC bf = new SimpleIOC(location);
        Wheel wheel = (Wheel) bf.getBean("wheel");
        System.out.println(wheel);
    }
}

Output:
Here Insert Picture Description

Two. AOP simple implementation

IOC is based on the realization of the proxy mode, Spring implemented in two IOC, when there is a proxy class interfaces, Spring dynamic proxy jdk the AOP to achieve, when the proxy class does not inherit an interface, Spring Cglib implemented using AOP.

1.SpringAOP some concepts

  1. Advice

It defines a logical execution timing of weaving and object

  1. Before the target method execution: before
  2. after: after the target method executes, then regardless of the target method returns the result of what is
  3. after-returning: the target method execution
  4. after-throwing: the target method throws an exception after execution
  5. around: before and after the execution of the target method will be called
  1. PointCut

Define the insertion point of execution

  1. Aspect

The first two groups and it is Aspect. That is what is executed when and where.

2. realization

  1. Define the interface section, the need to implement the interface of InvocationHandler, this interface has Invoke
    () method. When generating the proxy class behind the respective method is essentially calling this method.
package MySpringAOP;

import java.lang.reflect.InvocationHandler;

/**
 * @author Time
 * @created 2019/7/2
 */
public interface Advice extends InvocationHandler {
}


// Advice 的实现类
package MySpringAOP;

import java.lang.reflect.Method;

/**
 * @author Time
 * @created 2019/7/2
 */
public class BeforeAdvice implements Advice {
    private  Object bean;
    private MethodInvocation methodInvocation;
    public BeforeAdvice(Object bean, MethodInvocation methodInvocation){
        this.bean = bean;
        this.methodInvocation = methodInvocation;
    }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 在目标方法执行之前调用通知
        methodInvocation.invoke();
        return method.invoke(bean,args);
    }
}


  1. It is defined to be a proxy class that must implement an interface. Because the underlying jdk is through this interface to implement proxy class.
// 接口
package MySpringAOP;

/**
 * @author Time
 * @created 2019/7/2
 */
public interface HelloService {
    void sayHelloWorld();
}


// 接口实现类
package MySpringAOP;

/**
 * @author Time
 * @created 2019/7/2
 */
public class HelloServiceImpl implements HelloService {
    public void sayHelloWorld() {
        System.out.println("hello world!");
    }
}


  1. Adding an interface to a custom Advice
package MySpringAOP;

/**
 * @author Time
 * @created 2019/7/2
 */
public interface MethodInvocation {
    void invoke();
}

  1. Returns a proxy object class
package MySpringAOP;

import java.lang.reflect.Proxy;

/**
 * @author Time
 * @created 2019/7/2
 */
public class SimpleAOP {
    public static Object getProxy(Object bean,Advice advice){
        return Proxy.newProxyInstance(SimpleAOP.class.getClassLoader(), bean.getClass().getInterfaces(), advice);
    }
}

  1. AOP function test, in fact achieve the two agents here, first of all BeforeAdvice agents (packaging) HelloServiceImpl class. Finally returned to the real dynamic proxy class by proxy.
package MySpringAOP;

/**
 * @author Time
 * @created 2019/7/2
 */
public class SimpleAOPTest {
    public static void main(String[] args) {
        // 创建一个 MethodInvocation 实现类
        MethodInvocation logTask = new MethodInvocation() {
            public void invoke() {
                System.out.println("log task start");
            }
        };
        HelloServiceImpl helloServiceImpl = new HelloServiceImpl();

        // 创建一个advice
        Advice beforeAdvice = new BeforeAdvice(helloServiceImpl,logTask);

        // 为目标类生成代理
        HelloService helloServiceImplProxy = (HelloService) SimpleAOP.getProxy(helloServiceImpl,beforeAdvice);

        helloServiceImplProxy.sayHelloWorld();
    }
}


Results of the:
Here Insert Picture Description

Published 66 original articles · won praise 26 · views 10000 +

Guess you like

Origin blog.csdn.net/Time__Lc/article/details/94441981