JavaWeb 연구 노트 (21) 자신의 봄 IOC와 AOP를 실현하기

IOC와 AOP는 이해를 참조 심화하기 위해, 원리를 이해하기위한이 시간은 스프링 프레임 워크를 학습하고있다 티안 샤오 보에게이 블로그 IOC와 AOP의 기본 기능을 달성하기를.

A. IOC 간단한 구현

1. 구현 프로세스

  1. 라벨을 통과로드 XML 구성 파일,
  2. 클래스 로딩 해당 태그 ID와 클래스 속성, 클래스 속성을 얻고 반사 콩을 사용하여 만들었습니다.
  3. 가득 콩에 속성 값과 속성 값을 받고, 요소 태그를 순회.
  4. 빈은 빈 컨테이너에 등록했다.

2. 구현 코드

  1. SimpleIOC 클래스, IOC의 주요 구현 클래스
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);
    }
}

코드는 콘텐츠 XML 구성 파일을 획득 한 다음 인스턴스, 주입 파라미터를 생성하는 DOM 방법을 파싱하여, 비교적 간단하다. 빈 컨테이너에 가입하세요.

  1. 사출 타입은
    IOC의 컨테이너 성공적인 클래스 여부를 검출에 사용

Wheell 클래스

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 + '\'' +
                '}';
    }
}

자동차 카테고리

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 구성 파일
<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. 테스트 카테고리

성공 확인

/**
 * @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);
    }
}

출력 :
그림 삽입 설명 여기

두. AOP 간단한 구현

프록시 클래스가 인터페이스 상속하지 않는 경우 프록시 클래스 인터페이스, 스프링 동적 프록시 상기 AOP 달성 JDK있을 때 IOC는 프록시 모드의 실현에 기초 스프링 두 IOC 구현, 스프링 CGLIB는 AOP를 사용하여 구현.

몇 가지 개념을 1.SpringAOP

  1. 조언

그것은 직물 및 개체의 논리적 인 실행 시간을 정의

  1. 대상 메소드 실행 전 : 전
  2. 타겟 메소드를 실행 한 다음에 관계없이 타겟의 방법은 어떤 결과를 반환 한 후
  3. 후 복귀하는 단계 : 대상 실행 방법
  4. 이후 던지기 : 대상 방법은 실행 후 예외를 발생
  5. 주위 : 전 대상 메소드의 실행 후에 호출됩니다
  1. 포인트 컷

실행의 삽입 점을 정의

  1. 양상

처음 두 그룹과는 양상이다. 즉 언제, 어디서 실행되는 것입니다.

2. 실현

  1. 인터페이스 섹션의 InvocationHandler의 인터페이스를 구현해야 할 필요성을 정의,이 인터페이스는 호출이있다
    () 메소드를. 각각의 방법 뒤에 프록시 클래스를 생성 할 때 기본적으로이 메서드를 호출한다.
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. 인터페이스를 구현해야합니다 프록시 클래스로 정의된다. 기본 JDK는이 인터페이스를 통해 때문에 프록시 클래스를 구현합니다.
// 接口
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. 사용자 정의 조언에 인터페이스를 추가
package MySpringAOP;

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

  1. 프록시 객체 클래스를 돌려줍니다
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 기능 검사, 사실 먼저 BeforeAdvice 에이전트 (포장) HelloServiceImpl 클래스의, 여기에 두 개의 에이전트를 얻을 수 있습니다. 마지막으로 프록시에 의해 실제 동적 프록시 클래스에 돌아왔다.
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();
    }
}


결과 :
그림 삽입 설명 여기

게시 66 개 원래 기사 · 원 찬양 26 ·은 10000 +를 볼

추천

출처blog.csdn.net/Time__Lc/article/details/94441981