spring 动态代理开发的切入点表达式

spring 动态代理开发的切入点表达式

在前面总结了spring的动态代理开发的步骤,指定增强类(额外功能)的使用,那有了功能,还需要指定使用功能的地方,就需要切入表达式来指定切入的地点

1,演示文件结构和类实现

先看下文件目录和类实现,可以更好的演示切入点表达式所达到的效果

image-20210526184919130

cutexpress包

UserPoxyBefore

用于指定增强的方法,如果实现了代理则可以看到打印出的增强类方法名

import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class UserPoxyBefore implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("UserPoxyBefore.before");
    }
}

userservice2接口

用于实现UserServiceImpl_type

public interface UserService2 {
     void login(String id);
}

UserServiceImpl_type

用于测试同方法名不同参数个数

public class UserServiceImpl_type implements UserService2 {
    @Override
    public void login(String id) {
        System.out.println("org.Service.Cutexpress.UserServiceImpl_type.login"+id);
    }
}

cutexpress.UserServiceImpl

用于测试不同包的同类名,同方法名

public class UserServiceImpl implements UserService {

    @Override
    public void register(User user) {
        System.out.println("org.Service.Cutexpress.UserServiceImpl.register");
    }

    @Override
    public Boolean login(String name, String password) {
        System.out.println("org.Service.Cutexpress.UserServiceImpl.login "+name+" "+password );
        return true;
    }
}

UserServiceImpl_FB

用于测试同包不同类名

public class UserServiceImpl_FB implements UserService {

    @Override
    public void register(User user) {
        System.out.println("org.Service.Cutexpress.UserServiceImpl_FB.register");
    }
    @log
    @Override
    public Boolean login(String name, String password) {
        System.out.println("org.Service.Cutexpress.UserServiceImpl_FB.login "+name+" "+password );
        return true;
    }
}

service 包

实现各种UserService接口的类

public interface UserService {
    public void register(User user);

    public void login(String name, String password);
}

UserServiceImpl

用于测试不同包同方法名

public class UserServiceImpl implements UserService {

    @Override
    public void register(User user) {
        System.out.println("rg.Service.UserServiceImpl.register");

    }

    @Override
    public Boolean login(String name, String password) {
        System.out.println("rg.Service.UserServiceImpl.login "+name+" "+password );
        return true;
    }
}

配置文件

把各个类的bean写进去

expression暂时为空,等下填表达式测试

用的增强类UserPoxyBefore

<bean id="UserServicePiont" class="org.Service.Cutexpress.UserServiceImpl"/>
<bean id="UserServicePiont2" class="org.Service.UserServiceImpl"/>

<bean id="UserPoxyBefore" class="org.Service.Cutexpress.UserPoxyBefore"  />

<bean id="FB" class="org.Service.Cutexpress.UserServiceImpl_FB"/>
<bean id="type" class="org.Service.Cutexpress.UserServiceImpl_type"/>

<aop:config  >
    <aop:pointcut id="UserPoxyPC"  expression=""/>
    <aop:advisor advice-ref="UserPoxyBefore" pointcut-ref="UserPoxyPC"/>
</aop:config>

测试类

@Test
    public void test2() {
        ApplicationContext context=new ClassPathXmlApplicationContext("/ApplicationContext2.XML");
        //org.Service.UserServiceImpl 对比包
        UserService userService_= (UserService) context.getBean("UserServicePiont2");
        userService_.login("SY", "123456");
        userService_.register(new User());
        //org.Service.Cutexpress.UserServiceImpl 同类不同包
        UserService userService= (UserService) context.getBean("UserServicePiont");
        userService.login("SY", "123456");
        userService.register(new User());
        //org.Service.Cutexpress.UserServiceImpl_FB 同包不同类
        UserService userService2=(UserService) context.getBean("FB");
        userService2.login("SY", "123456");
        //org.Service.Cutexpress.UserServiceImpl_type 实现的方法只有一个
        UserService2 userService3=(UserService2) context.getBean("type");
        userService3.login("32");
    }

2.切入点表达式

1.expression函数(方法->类->包)

对于方法:

​ 对所有方法都代理:*** (..)*

​ 执行结果:所有方法均被代理

image-20210530235342429

​ 对于所有login方法: *** login(..)**

image-20210530235419139

​ 指定参数 数量,类型

​ 对于只有一个String参数的:login(String)

image-20210530235602982

​ 对于有二个String参数的 :*** login(String,String)**

image-20210530235706326

​ 参数和..连用:*** login(String,..)**

​ 表示第一个参数是String的所有方法

image-20210530235822414

​ 指定非Java.lang包中的对象:*** register(org.User)**

image-20210530235916137

​ 精确切入某个方法(权限名命)特别注意星号

​ *** org.Service.Cutexpress.UserServiceImpl_FB.login(..)**

image-20210531000826361

对于类:

​ 指定某个类的所有方法

​ *** org.Service.Cutexpress.UserServiceImpl.*(..)**

image-20210531000951845

对于多级包(搜索所有包中符合方法名字的类)

​ *** ..UserServiceImpl.(..)**

image-20210531001114977

对于包:

​ 对于某个包的所有类的方法

​ *** org.Service..(..)**

image-20210531001237429

​ 对于某个包的子包


$$

  • org.Service...(..)
    $$
    image-20210531001405863

2.其他函数、

args

​ args主要用于参数的匹配,填写参数就可以,注意在expression中的expression替换为args 例如:

<aop:pointcut id="UserPoxyPC"  expression=" args(String)  "/>

​ args(String),匹配一个String参数的方法

image-20210531002154886

within

​ within 用于对包,类的匹配(*代表类或者包)

​ within(*..UserServiceImpl) 匹配所有的UserServiceImpl类

image-20210531002345607

​ within(org.Service.Cutexpress..*) 匹配所有的org.Service.Cutexpress包下的类

image-20210531002414954

3.对于注解

​ 自定义一个注解

package org;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface log {
}

在想实现代理的类上注解,如UserServiceImpl_FB

image-20210531002728322

4.对于不同函数的运算

配置文件如:

 <aop:pointcut id="UserPoxyPC"  expression="execution(* login(..)) and args(String)"/>

and

比如 所有的login方法 同时满足 一个String参数都代理

execution(* login(..)) and args(String)

image-20210531003017603

or

比如所有的login方法 和 一个String参数的方法都代理

login(..) or args(String)

image-20210531003156040

3.总结

对于一个方法的实现我们要有以下要素:

权限 返回值 方法名(参数)

抽象为

权限 返回值 方法名 (参数)
* * (..)

不难发现*** (..)* 就是所有的方法的表达方式

无论需求是方法 类 还是包

第一个*就代表权限 第二个是路径 第三个是方法,以此类推。

同时一个表达式可以由多个表达式实现,不要拘泥于某个表达方式

posted on 2021-05-31 00:47  NathenJames  阅读(105)  评论(0编辑  收藏  举报