IOC와 AOP는 이해를 참조 심화하기 위해, 원리를 이해하기위한이 시간은 스프링 프레임 워크를 학습하고있다 티안 샤오 보에게이 블로그 IOC와 AOP의 기본 기능을 달성하기를.
A. IOC 간단한 구현
1. 구현 프로세스
- 라벨을 통과로드 XML 구성 파일,
- 클래스 로딩 해당 태그 ID와 클래스 속성, 클래스 속성을 얻고 반사 콩을 사용하여 만들었습니다.
- 가득 콩에 속성 값과 속성 값을 받고, 요소 태그를 순회.
- 빈은 빈 컨테이너에 등록했다.
2. 구현 코드
- 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 방법을 파싱하여, 비교적 간단하다. 빈 컨테이너에 가입하세요.
- 사출 타입은
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 + '\'' +
'}';
}
}
- 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>
- 테스트 카테고리
성공 확인
/**
* @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
- 조언
그것은 직물 및 개체의 논리적 인 실행 시간을 정의
- 대상 메소드 실행 전 : 전
- 타겟 메소드를 실행 한 다음에 관계없이 타겟의 방법은 어떤 결과를 반환 한 후
- 후 복귀하는 단계 : 대상 실행 방법
- 이후 던지기 : 대상 방법은 실행 후 예외를 발생
- 주위 : 전 대상 메소드의 실행 후에 호출됩니다
- 포인트 컷
실행의 삽입 점을 정의
- 양상
처음 두 그룹과는 양상이다. 즉 언제, 어디서 실행되는 것입니다.
2. 실현
- 인터페이스 섹션의 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);
}
}
- 인터페이스를 구현해야합니다 프록시 클래스로 정의된다. 기본 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!");
}
}
- 사용자 정의 조언에 인터페이스를 추가
package MySpringAOP;
/**
* @author Time
* @created 2019/7/2
*/
public interface MethodInvocation {
void invoke();
}
- 프록시 객체 클래스를 돌려줍니다
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);
}
}
- 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();
}
}
결과 :