2018-01-31

2018-01-31  本文已影响0人  zigzh

spring aop

@(iJava)[spring framework]

[toc]


aop底层原理
采用动态代理设计模式面向对象思想的为每个方法添加预热方法和擦屁股方法:-),

public class Test {
    public static void main(String[] args) {
        //System.getProperties().put("sun.misc.ProxyG", arg1)
        jdkProxy();
    }   
    public static void jdkProxy(){
        JdkProxy proxy = new JdkProxy();
        IUser user = (IUser)proxy.bind(new User());
        //jdk版本底层是proxy 间接implements IUser,可以强转(但没有继承User)
        String result = user.add("1", "zhangsan");
        System.out.println("result:"+result);
    }
    public static void cglibProxy(){
        CglibProxy proxy = new CglibProxy();
        IUser user = (User)proxy.bind(new User());
        String result = user.add("etoak", "et1710");
        System.out.println("返回结果:"+result);
    }
}
为了实现添头加尾,那么首先需要得到这个方法
public class JdkProxy {
    public Object bind(final Object target) {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), 
                new InvocationHandler() {
                //指明生成代理对象使用哪个类装载器,得到要处理的数据
                //指明生成哪个对象的代理对象,通过接口指定
                //类将代理实例传递给内部类,指明产生的这个代理对象要做什么事情
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
                    //拿到类装载器提供的数据,组装一个target.getClass().getInterfaces()的实现类
                        start();
                        //核心业务逻辑
                        Object result = method.invoke(target, args);
                        end();
                        return result;
                    }
                });
    }       
}
public class CglibProxy implements MethodInterceptor{
    public Object bind(Object target){
        Enhancer e = new Enhancer();
        e.setSuperclass(target.getClass());
        e.setCallback(this);
        return e.create();
    }
    @Override
    public Object intercept(Object object, Method method, Object[] args,
            MethodProxy proxy) throws Throwable {
        start();
        Object result = proxy.invokeSuper(object, args);
        end();
        return result;
    }
}
public interface IUser {
    public String add(String id,String name);
}
public class User implements IUser {
    @Override
    public String add(String id, String name) {
        System.out.println("ID:"+id);
        System.out.println("Name:"+name);
        return id+"|"+name;
    }
}

xml配置方法

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">

切入点表达式
* com.etoak.controller.LoginController.login(..)

execution(* com.etoak.controller..add(..))
and execution(
com.etoak.controller.*.del(..))

execution(* com.etoak.controller..add(..))
|| execution(
com.etoak.controller.*.del(..))


aop注解

注解原理首先反射加载类(方法),然后捕获注解,如果存在切面注解,那么继续...

public class BeforeAdvice implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object object)throws Throwable {

    }   
}

public class AfterAdvice implements AfterReturningAdvice{
    @Override
    public void afterReturning(Object result, Method method, Object[] args,Object object) throws Throwable {

    }   
}

    @Around(value="etoak()")
    public Object around(ProceedingJoinPoint pjp)throws Throwable{
        start();//before()
        Object result = pjp.proceed();
        end();//after()
        return result;
    }

xml标签 + 实现MethodInterceptor接口

public class AroundAdvice implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable{
        Object object = invocation.getThis();
        Method method = invocation.getMethod();
        Object[] args = invocation.getArguments();

        System.out.println(object.getClass().getName());
        start();
        Object result = invocation.proceed();
        end();
        return result;
    }

    public void start() {
        //
    }

    public void end() {
        //
    }

}

Tag interface for throws advice.
There are not any methods on this interface, as methods are invoked by reflection. Implementing classes must implement methods of the form:
void afterThrowing([Method, args, target], ThrowableSubclass);Some examples of valid methods would be:
public void afterThrowing(Exception ex)
public void afterThrowing(RemoteException)
public void afterThrowing(Method method, Object[] args, Object target, Exception ex)
public void afterThrowing(Method method, Object[] args, Object target, ServletException ex)
The first three arguments are optional, and only useful if we want further information about the joinpoint, as in AspectJ after-throwing advice.

注解版:同时实现了打印日志功能

    @AfterThrowing(value="etoak()",throwing="e")
    public void ex(JoinPoint jp,Exception e){
        try (OutputStream os = new FileOutputStream("C:/1.txt",true);
                PrintWriter out = new PrintWriter(os)) {
            e.printStackTrace(out);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

标签版:

public class ThrowAdvice implements ThrowsAdvice {
    public void afterThrowing(Method method, Object[] args, Object target,Exception ex) {
        System.out.println("目标对象:" + target.getClass().getName());
        System.out.println("目标对象方法:" + method.getName());
        System.out.println(args);
        System.out.println(ex.getMessage());
        try (OutputStream os = new FileOutputStream("C:/1.txt",true);
                PrintWriter out = new PrintWriter(os)) {
            ex.printStackTrace(out);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

参考文档:
https://www.cnblogs.com/xdp-gacl/p/3971367.html

上一篇 下一篇

猜你喜欢

热点阅读