Spring入门笔记--AOP

动态代理

代理模式类图

代理的基本分类: 静态代理 + 动态代理,分类的标准是 “代理关系是否在编译期确定;

JDK动态代理

样例

TargetInterface.java

public interface TargetInterface {
    public void save();
}

Target.java

public class Target implements TargetInterface {
    public void save(){
        System.out.println("save...");
    }
}

Advice.java

public class Advice {
    public void before() {
        System.out.println("before增强");
    }

    public void after() {
        System.out.println("after增强");
    }
}

ProxyTest.java

public class ProxyTest {
    public static void main(String[] args) {
        final Target target = new Target();
        final Advice advice = new Advice();
        TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(
                // 目标对象类加载器
                target.getClass().getClassLoader(),
                // 目标对象相同的接口字节码对象数组
                target.getClass().getInterfaces(),
                // 调用代理对象任何方法,实际执行的是invoke方法
                new InvocationHandler() {
                    public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
                        advice.before();
                        Object invoke = method.invoke(target, args);
                        advice.after();
                        return invoke;
                    }}
        );
        proxy.save();
    }
}

cglib动态代理

样例

Target.java,不需要实现接口,与jdk的区别

public class Target {
    public void save(){
        System.out.println("save...");
    }
}

ProxyTest.java

public class ProxyTest {
    public static void main(String[] args) {
        // 目标对象
        final Target target = new Target();
        // 增强对象
        final Advice advice = new Advice();
        // 1、创建增强器
        Enhancer enhancer = new Enhancer();
        // 2、设置父类(目标)
        enhancer.setSuperclass(target.getClass());
        // 3、设置回调
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                advice.before();
                Object invoke = method.invoke(target, args);
                advice.after();
                return invoke;
            }
        });
        // 4、创建代理对象
        Target proxy = (Target)enhancer.create();

        proxy.save();
    }
}

Spring的AOP概念

术语:

  1. Target:代理的目标对象
  2. Proxy: 代理类
  3. Joinpoint: 连接点,spring中指方法
  4. PointCut: 切入点,定义对哪些Joinpoint进行拦截
  5. Advice: 通知/增强,拦截到JoinPoint后的操作
  6. Aspect:切面,PointCut+Advice
  7. Weaving: 织入,把增强应用到目标对象创建代理对象的过程。spring采用动态代理织入;Aspect J采用编译期织入和类装载期织入。

aop的xml配置

applicationContext.xml

        <!--目标对象-->
        <bean id="target" class="com.example.yihao_spring_aop.aop.Target"/>
        <!--切面对象-->
        <bean id="myAspect" class="com.example.yihao_spring_aop.aop.MyAspect"/>
        <!--配置织入-->
        <aop:config>
                <aop:aspect ref="myAspect">
                        <aop:before method="before" pointcut="execution(public void com.example.yihao_spring_aop.aop.Target.save())"></aop:before>
                </aop:aspect>
        </aop:config>

test

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AopTest {
    @Autowired
    private TargetInterface target;

    @Test
    public void test() {
        target.save();
    }
}

切点表达式

execution(public void com.example.yihao_spring_aop.aop.Target.save())
返回类型、包、类、方法可以是使用代表通配符
参数列表可以使用..表示任意参数
修饰符可以省略
比如:execution(void com.example.
.aop.Target.*(..))

aop的注解配置

applicationContext_anno.xml

  <!--组件扫描-->
  <context:component-scan base-package="com.example.yihao_spring_aop.anno"/>
  <!--aop自动代理-->
  <aop:aspectj-autoproxy/>

MyAspect.java

@Component("myAspect")
@Aspect
public class MyAspect {
    @Before("execution(public void com.example.yihao_spring_aop.anno.Target.save())")
    public void before() {
        System.out.println("前置before");
    }

    public void after() {
        System.out.println("后置after");
    }
}

可以定义Pointcut
MyAspect.java

@Component("myAspect")
@Aspect
public class MyAspect {
    @Before("pointCut()")
    public void before() {
        System.out.println("前置before");
    }

    public void after() {
        System.out.println("后置after");
    }

    //定义PointCut表达式
    @Pointcut("execution(void com.example.yihao_spring_aop.anno.*.*(..))")
    public void pointCut() {}
}
posted @   Saski&Naruto  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示