Spring 手动实现AOP编程

在介绍手动实现AOP之前我们需要了解几个知识点

业务代码和关注点代码,下面拖过一个例子来形象的解释着二者的意思

关注点代码,就是指重复执行的代码

业务代码与关注点代码分离,关注点代码写一次即可;

开发者只需要关注核心业务,运行时期,执行核心业务代码时候通过代理动态植入关注点代码;

接下来来介绍介个名词

关注点:重复代码就叫做关注点;

切面:关注点形成的类,就叫切面(类), 面向切面编程,就是指 对很多功能都有的重复的代码抽取,再在运行的时候往业务方法上动态植入“切面类代码”。

切入点:执行目标对象方法,动态植入切面代码。可以通过切入点表达式,指定拦截哪些类的哪些方法; 给指定的类在运行的时候植入切面类代码。

下面通过一个案例来手动实现AOP(动态代理实现)

首先写一个接口

package com.Demo5;

public interface IUserDao {
    public void save();
}

然后写一个类去实现这个接口

package com.Demo5;

import org.springframework.stereotype.Component;

@Component("userDao")
public class UserDao implements  IUserDao {
    @Override
    public void save() {
        System.out.println("-----------开启连接-----------");
    }
}

其次在写一个MyAop类,主要存放重复的代码

package com.Demo5;

import org.springframework.stereotype.Component;
//通过注解直接配置对象
@Component
public   class MyAop {
    public void beginTran(){
        System.out.println("...............开启事务");
    }
    public void commite(){
        System.out.println("...............提交事务");
    }
}

然后写一个代理类

package com.Demo5;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;


public class ProxyFactory {
    private  static MyAop aop;
    private  static Object target;
    public static  Object getProxyFactory(Object _target,MyAop _aop){
        //目标对象
        target = _target;
        aop = _aop;
        //在目标方法去传入目标参数和AOP参数
        return   Proxy.newProxyInstance(target.getClass().getClassLoader()
                , target.getClass().getInterfaces()
                , new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        aop.beginTran();
                        //通过反射获取方法返回值
                        Object resultValue = method.invoke(target,args);
                        aop.commite();
                        return resultValue;
                    }
                });
    }
}

然后再去配置bean1.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <!--开启注解扫描-->
    <context:component-scan base-package="com.Demo5"></context:component-scan>
    <!--配置工厂对象-->
    <!--我们的方法是静态的所以需要通过类名来调用方法-->
    <bean id="userProxy" class="com.Demo5.ProxyFactory" factory-method="getProxyFactory">
        <!--因为我们写的getProxyFactory方法有2个参数所以需要配置参数-->
        <constructor-arg index="0" ref="userDao"></constructor-arg>
        <constructor-arg  index="1" ref="myAop"></constructor-arg>
    </bean>
</beans>

最后写一个测试类

package com.Demo5;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;


public class Test3 {
    public static void main(String []args){
        ApplicationContext  ap = new ClassPathXmlApplicationContext("bean1.xml");
        IUserDao proxy = (IUserDao) ap.getBean("userProxy");
        proxy.save();
    }
}

运行结果如下

猜你喜欢

转载自blog.csdn.net/wyf2017/article/details/81224633