Spring IOC AOP的简单实现

最简单的IOC容器只需要4步即可实现

  1. 加载xml配置文件,遍历其中的标签
  2. 获取标签中的id和class属性,加载class属性对应的类,并创建bean
  3. 遍历标签中的标签,获取属性值,并将属性值填充到bean中
  4. 将bean注册到bean容器中

SimpleIOC

import org.w3c.dom.Document;
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;

public class SimpleIOC {

    private Map<String,Object> beanMap = new HashMap<>();

    public SimpleIOC(String location) throws Exception{
        loadBeans(location);
    }

    public Object getBean(String name){
        Object bean = beanMap.get(name);
        if (bean == null){
            throw new IllegalArgumentException("没有叫"+name+"的bean");
        }
        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 参数错误");
                            }

                            //将引用填充到相关字段中
                            declaredField.set(bean,getBean(ref));
                        }

                        //将bean注册到bean容器中
                        registerBean(id,bean);
                    }
                }
            }
        }
    }

    private void registerBean(String id,Object bean){
        
        beanMap.put(id,bean);
    }
}

Car:

package com.sc.domain;

import java.io.Serializable;

public class Car implements Serializable {

    private String name;
    private String length;
    private String width;
    private String height;
    private Wheel wheel;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getLength() {
        return length;
    }

    public void setLength(String length) {
        this.length = length;
    }

    public String getWidth() {
        return width;
    }

    public void setWidth(String width) {
        this.width = width;
    }

    public String getHeight() {
        return height;
    }

    public void setHeight(String height) {
        this.height = height;
    }

    public Wheel getWheel() {
        return wheel;
    }

    public void setWheel(Wheel wheel) {
        this.wheel = wheel;
    }

    @Override
    public String toString() {
        return "Car{" +
                "name='" + name + '\'' +
                ", length='" + length + '\'' +
                ", width='" + width + '\'' +
                ", height='" + height + '\'' +
                ", wheel=" + wheel +
                '}';
    }
}

Wheel:

package com.sc.domain;

public class Wheel {
    private String brand;
    private String specification;

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public String getSpecification() {
        return specification;
    }

    public void setSpecification(String specification) {
        this.specification = specification;
    }

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

ioc.xml

<beans>
    <bean id="wheel" class="com.sc.domain.Wheel">
        <property name="brand" value="Michelin"></property>
        <property name="specification" value="265/60 R18"/>
    </bean>

    <bean id="car" class="com.sc.domain.Car">
        <property name="name" value="benchi G 500"/>
        <property name="length" value="4717mm"/>
        <property name="width" value="1949mm"/>
        <property name="height" value="1855mm"/>
        <property name="wheel" ref="wheel"/>
    </bean>
</beans>

main:

public class SimpleIOCTest {

    public static void main(String args[]) throws Exception {
        String location = SimpleIOC.class.
                getClassLoader().getResource("ioc.xml").getFile();
        SimpleIOC bf = new SimpleIOC(location);
        Wheel wheel = (Wheel) bf.getBean("wheel");
        System.out.println(wheel);
        Car car = (Car) bf.getBean("car");
        System.out.println(car);
    }
}

结果:

Wheel{brand='Michelin', specification='265/60 R18'}
Car{name='benchi G 500', length='4717mm', width='1949mm', height='1855mm', wheel=Wheel{brand='Michelin', specification='265/60 R18'}}

简单的AOP实现:

五种类型的通知

  • Before:在目标法执行前执行通知
  • After:在目标法执行后执行通知,不关系返回值是什么
  • After-returning:在目标方法执行后,执行通知
  • After-throwing:目标方法抛出异常后执行通知
  • Around:目标法被通知包裹,通知在目标方法执行前后都会被调用

切点:在何处通知,通过匹配规则找到连接点,AOP会在这些连接点上织入通知

切面:切面包含了 通知 和 切点 ,在何时何处执行切面逻辑

此处我们通过动态代理实现AOP,步骤如下:

  1. 定义一个包含切面逻辑的对象logMethodInvocation
  2. 定义一个Advice对象(实现了InvocationHandler接口),并将上面的logMethodInvocation和目标对象传入
  3. 将上面的Advice对象和目标对象传给JDK动态代理方法,为目标对象生成代理

MethodInvocation:

/**
 * 他的实现类包含切面逻辑
 */
public interface MethodInvocation {
    void invoke();
}

Advice:

/**
 * 继承了InvocationHandler接口
 * 每个代理类的调用处理程序都必须实现InvocationHandler接口
 * 相当于所有通知类的父类
 */
public interface Advice extends InvocationHandler {
}

BeforAdvice:

/**
 * 实现了Advice接口,是一个前置通知
 */
public class BeforeAdvice implements Advice {

    //代理类中的真实对象
    private Object bean;
    //要实现的逻辑
    private MethodInvocation methodInvocation;

    public BeforeAdvice(Object bean,MethodInvocation methodInvocation){
        this.bean = bean;
        this.methodInvocation = methodInvocation;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //在目标方法执行前 调用通知
        methodInvocation.invoke();
        //目标法执行
        return method.invoke(bean,args);
    }
}

SimpleAOP:

import java.lang.reflect.Proxy;
/**
 * 生成代理类
 */
public class SimpleAOP {

    public static Object getProxy(Object bean,Advice advice){
        return Proxy.newProxyInstance(SimpleAOP.class.getClassLoader(),
                bean.getClass().getInterfaces(),advice);
    }
}

HelloService接口:

/**
 * 目标对象接口
 */
public interface HelloService {
    void sayHelloWorld();
}

HelloServiceImpl:

/**
 * 接口实现类
 */
public class HelloServiceImpl implements HelloService{
    @Override
    public void sayHelloWorld() {
        System.out.println("hello world aop!");
    }
}

SimpleAOPTest:

/**
 * aop测试类
 */
public class SimpleAOPTest {

    public static void main(String[] args) {
        //1.创建一个MethodInvocation实现类
        MethodInvocation logTask = ()-> System.out.println("log task start");
        //目标对象
        HelloService helloServiceImpl = new HelloServiceImpl();
        //2.创建一个Advice
        Advice beforeAdvice = new BeforeAdvice(helloServiceImpl,logTask);
        //3.为目标对象生成代理
        HelloService helloServiceImplProxy = (HelloService)
                SimpleAOP.getProxy(helloServiceImpl,beforeAdvice);

        helloServiceImplProxy.sayHelloWorld();
    }
}

最后的输出:

log task start
hello world aop!
购物商城项目采用PHP+mysql有以及html+css jq以及layer.js datatables bootstorap等插件等开发,采用了MVC模式,建立一个完善的电商系统,通过不同用户的不同需求,进行相应的调配和处理,提高对购买用户进行配置….zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值