美文网首页
Spring IOC 和 AOP

Spring IOC 和 AOP

作者: 林亚希 | 来源:发表于2019-04-08 07:53 被阅读0次

简单IOC和AOP实现

IOC

1.简述

控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入。

2.关键点

最简单的IOC实现只需要简单的4个步骤。
1.加载XML配置文件,遍历其中标签。
2.获取标签重点Id,加载标签中的class,创建bean。
3.遍历标签获取属性值,并将属性值填充到bean中。
4.注册bean到bean容器中。

3.代码实现

SimpleIOC  (重点)IOC实现类
Brand  bean 类
Car      bean类
IOCTest  测试方法  
testIOC.xml 配置文件

先上配置文件,我们要初始化一个宝马品牌的车子

<beans>
    <bean id="brand" class="com.kinsec.spring.IOC.Brand">
        <property name ="brand" value ="BMW"></property>
        <property name ="wheel" value ="R17"></property>
        <property name ="engine" value ="2.0T"></property>
    </bean>
    <bean id="car" class="com.kinsec.spring.IOC.Car">
        <property name ="color" value ="red"></property>
        <property name ="price" value ="30"></property>
        <property name ="brand" ref="brand"></property>
    </bean>
</beans>

对应的bean文件

public class Car {

    private String color;
    private String price;
    private Brand brand;

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public String getPrice() {
        return price;
    }

    public void setPrice(String price) {
        this.price = price;
    }

    public Brand getBrand() {
        return brand;
    }

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

    @Override
    public String toString() {
        return "Car{" +
                "color='" + color + '\'' +
                ", price='" + price + '\'' +
                ", brand=" + brand +
                '}';
    }
}


public class Brand {

    private String brand ;
    private String wheel ;
    private String engine ;

    public String getBrand() {
        return brand;
    }

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

    public String getWheel() {
        return wheel;
    }

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

    public String getEngine() {
        return engine;
    }

    public void setEngine(String engine) {
        this.engine = engine;
    }

    @Override
    public String toString() {
        return "Brand{" +
                "brand='" + brand + '\'' +
                ", wheel='" + wheel + '\'' +
                ", engine='" + engine + '\'' +
                '}';
    }
}

上重点代码


public class SimpleIOC {

    //放置注册的bean
    private Map<String, Object> beanMap = new HashMap<String, Object>();

    //传入配置文件为参数
    public SimpleIOC(String resource) throws Exception{
        loadBeans(resource);
    }
    //加载beans
    private void loadBeans(String resource) throws Exception{

        //1.加载XML配置文件,遍历其中标签
        InputStream inputStream = new FileInputStream(resource);
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder = factory.newDocumentBuilder();
        Document document = documentBuilder.parse(inputStream);
        Element root = document.getDocumentElement();
        NodeList nodes = root.getChildNodes();

        //遍历每个bean标签
        for (int i=0 ; i<nodes.getLength();i++){
            //获取标签重点Id,加载标签中的class,创建bean
            Node node = nodes.item(i);
            if (node instanceof Element){
                Element ele = (Element) node;
                String id = ele.getAttribute("id");
                String className = ele.getAttribute("class");

                //反射类
                Class beanClass =  Class.forName(className);

                //创建bean
                Object bean = beanClass.newInstance();

                //遍历标签
                NodeList propNodes = ele.getElementsByTagName("property");
                for (int j = 0;j<propNodes.getLength();j++){
                    Node propNode = propNodes.item(j);
                    if (propNode instanceof Element){
                        //3.遍历标签获取属性值,并将属性值填充到bean中
                        Element propElement = (Element) propNode;
                        String name = propElement.getAttribute("name");
                        String value = propElement.getAttribute("value");

                        //利用反射机制将bean相关字段访问权限设置为可以访问
                        Field field = bean.getClass().getDeclaredField(name);
                        field.setAccessible(true);

                        if (null != value && value.length()>0){
                            field.set(bean,value);
                        }else{
                            String ref = propElement.getAttribute("ref");
                            if (null == ref || ref.length() == 0 ){
                                throw new IllegalArgumentException("ref 配置错误");
                            }
                            field.set(bean,getBean(ref));
                        }

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

            }
        }
    }
    //获取bean
    public Object getBean(String name){
        Object bean = beanMap.get(name);
        if (null ==  bean){
            throw new IllegalArgumentException(name + "bean 没有被注册!");
        }
        return bean;

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

AOP

1.简述

AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。spring是基于代理模式的。

2.基本概念

通知(Advice)

before advice, 在 join point 前被执行的 advice. 
after return advice, 在一个 join point 正常返回后执行的 advice
after throwing advice, 当一个 join point 抛出异常后执行的 advice
after(final) advice, 无论一个 join point 是正常退出还是发生了异常, 都会被执行的 advice.
around advice, 在 join point 前和 joint point 退出后都执行的 advice. 这个是最常用的 advice.
introduction,introduction可以为原有的对象增加新的属性和方法。

切点(Pointcut)

如果说通知定义了在何时执行通知,那么切点就定义了在何处执行通知。所以切点的作用就是
通过匹配规则查找合适的连接点(Joinpoint),AOP 会在这些连接点上织入通知。

切面(Aspect)

 Aspect 声明类似于 Java 中的类声明,在 Aspect 中会包含着一些切点以及相应的通知。

3.关键点

简单的AOP实现的步骤,基于JDK的动态代理实现。
1.定义一个切面逻辑的对象。
2.定义一个通知对象,并将上面的对象和目标对象传入。
3.为目标对象生成代理

4.代码实现

基于JDK动态代理的实现
1.具体实现类

Advice  //(重要)通知接口实现InvocationHandler
BeforeAdvice   //(重要)前置通知
Car  //业务接口
CarImpl // 业务实现
MethodInvocation  //具体通知业务操作
MethodInvocationImpl //实现类
SimpleAOP  //(重要)生成代理类
Test  //测试类

1.(重要)通知接口实现InvocationHandler

public interface Advice extends InvocationHandler {
}

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);
    }
}

3.业务接口与实现

public interface Car {
    void create();
}
public class CarImpl implements Car{
    public void create() {
        System.out.println("创建一辆车子");
    }
}

4.具体通知与实现

public interface MethodInvocation {
    void invoke();
}
public class MethodInvocationImpl implements MethodInvocation{
    public void invoke() {
        System.out.println("----AOP之代理模式----");
    }
}

5.代理类

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

6.测试类

public class Test {

    public static void main(String[] args) {

        //1创建实现类
        MethodInvocation methodInvocation =  new MethodInvocationImpl();
        CarImpl car = new CarImpl();
        //2创建一个通知
        Advice beforeAdvice = new BeforeAdvice(car,methodInvocation);
        //3生成代理
        Car carProxy = (Car) SimpleAOP.getProxy(car,beforeAdvice);
        carProxy.create();
    }
}

相关文章

网友评论

      本文标题:Spring IOC 和 AOP

      本文链接:https://www.haomeiwen.com/subject/sswfiqtx.html