AOP概念及在Spring中的使用

1、AOP的使用场景

在业务模块中,存在一种通用的系统性需求,如日志、事务管理等。
在常规的方法中,会在业务代码中直接嵌入平台代码。但这样是2种不相关的代码混杂,不方便管理。
通过AOP就可以实现在不侵入业务代码的情况下,实现统一的平台需求。
举个例子,如一个类有100个方法,都要嵌入日志代码吗?修改了怎么办?
AOP是一种编程概念,通过JDK远程方法也可以实现,spring中更容易了,写写配置就好。

2、AOP的术语

  1. 切面:Aspect,交叉的业务逻辑,如日志、事务管理。也叫对业务代码增强。
  2. 织入:Weaving,把切面代码插入主业务代码过程。
  3. 连接点:JoinPort,可以被织入的方法。指主业务中的方法。
  4. 切入点:PointCut,切面实际织入的方法。不是所有连接点都被织入。
  5. 目标对象:Target,目标对象,要被增强的对象。
  6. 通知:可以指定织入时机,无法指定切入点。每个连接点都会增强。
  7. 顾问:包含通知,可以针对具体连接点。

简单来说:AOP就是在业务代码中插入增强代码。包含2类4个要素

  1. 业务代码侧:目标代码,目标方法。
  2. 增强代码侧:增强的内容,触发的时机。

3、用JDK实现AOP:动态代理

public interface IUser {
    
    
    public String sayHello(String msg);
    public String goRun();
}

public class UserImpl implements IUser {
    
    
    @Override
    public String sayHello(String msg) {
    
    
        System.out.println( "你好,"+msg);
        return "";
    }

    public String goRun() {
    
    
        System.out.println( "i'm running");
        return "i'm running";
    }
	
	public static void main(String[] args) {
    
    
        final IUser target3 = new UserImpl();
       /*a proxy class that is defined in the specified class loader
     *          and that implements the specified interfaces
     * 所以第1、2个参数分别是目标类和目标类实现的接口*/
        IUser proxy3 = (IUser) Proxy.newProxyInstance(target3.getClass().getClassLoader(), target3.getClass().getInterfaces(), new InvocationHandler() {
    
    

            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
            /**代理类里重构了invoke方法,代理类的方法调用时,是派发到代理类内部的
        目标类上执行的。
        但是,invoke方法里可以添加切面了*/
                //前置通知
                System.out.println("判断用户是否有权限进行操作");
                //目标类方法
                Object obj = method.invoke(target3, args);
                //后置通知
                System.out.println("记录用户执行操作的用户信息、更改内容和时间等");
                return obj;
            }
        });

        Object obj3 = proxy3.sayHello("地球");
    }
}

实现方法:
1.目标类必须实现了接口;
2.用Proxy.newProxyInstance创建代理类
3.代理类包含了目标类实例,重构了invoke方法
4.在代理类的invoke方法中,执行目标类的方法,并可以加入前后通知

4、spring中AOP的实现

增强代码,已后置通知为例

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class MyMethodBeforeAdvice implements MethodBeforeAdvice {
    
    
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
    
    
        System.out.println("执行前置通知方法");
    }
}

ApplicationContext.xml配置

    <!--注册目标对象-->
    <bean id="myUserSerice" class="master3.UserImpl"></bean>

    <!--注册切面:通知-->
    <bean id="myAdvice" class="master3.MyMethodBeforeAdvice"/>

    <!--注册代理工厂-->
    <bean id="serviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!--指定目标对象,没有目标方法,因为是advice,不能指定方法,全部增强了-->
        <property name="target" ref="myUserSerice"> </property>
        <!--指定增强代码,时机是后置通知,通过继承设定了-->
        <property name="interceptorNames" value="myAdvice" ></property>

    </bean>

测试代码:

@Test
    public void test01(){
    
    
        ApplicationContext ac = new ClassPathXmlApplicationContext("ApplicationContext.xml");
        IUser myUser=(IUser)ac.getBean("serviceProxy");
        myUser.sayHello("地球");
        myUser.goRun();
    }

输出

执行前置通知方法
你好,地球
执行前置通知方法
i'm running

总结

  1. AOP是一种编程方法
  2. 适用于不修改业务代码的情况下对其增强
  3. 记住2类4概念:目标代码,目标方法;增强代码,触发时机。
  4. spring里改改参数文件就能实现

猜你喜欢

转载自blog.csdn.net/heroicpoem/article/details/104602743
今日推荐