spring 动态代理开发的切入点表达式
Posted NathenJames
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring 动态代理开发的切入点表达式相关的知识,希望对你有一定的参考价值。
spring 动态代理开发的切入点表达式
在前面总结了spring的动态代理开发的步骤,指定增强类(额外功能)的使用,那有了功能,还需要指定使用功能的地方,就需要切入表达式来指定切入的地点
1,演示文件结构和类实现
先看下文件目录和类实现,可以更好的演示切入点表达式所达到的效果
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函数(方法->类->包)
对于方法:
对所有方法都代理:*** (..)*
执行结果:所有方法均被代理
对于所有login方法: *** login(..)**
指定参数 数量,类型
对于只有一个String参数的:login(String)
对于有二个String参数的 :*** login(String,String)**
参数和..连用:*** login(String,..)**
表示第一个参数是String的所有方法
指定非Java.lang包中的对象:*** register(org.User)**
精确切入某个方法(权限名命)特别注意星号
*** org.Service.Cutexpress.UserServiceImpl_FB.login(..)**
对于类:
指定某个类的所有方法
*** org.Service.Cutexpress.UserServiceImpl.*(..)**
对于多级包(搜索所有包中符合方法名字的类)
*** ..UserServiceImpl.(..)**
对于包:
对于某个包的所有类的方法
*** org.Service..(..)**
对于某个包的子包
$$
- org.Service...(..)
$$
2.其他函数、
args
args主要用于参数的匹配,填写参数就可以,注意在expression中的expression替换为args 例如:
<aop:pointcut id="UserPoxyPC" expression=" args(String) "/>
args(String),匹配一个String参数的方法
within
within 用于对包,类的匹配(*代表类或者包)
within(*..UserServiceImpl) 匹配所有的UserServiceImpl类
within(org.Service.Cutexpress..*) 匹配所有的org.Service.Cutexpress包下的类
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
4.对于不同函数的运算
配置文件如:
<aop:pointcut id="UserPoxyPC" expression="execution(* login(..)) and args(String)"/>
and
比如 所有的login方法 同时满足 一个String参数都代理
execution(* login(..)) and args(String)
or
比如所有的login方法 和 一个String参数的方法都代理
login(..) or args(String)
3.总结
对于一个方法的实现我们要有以下要素:
权限 返回值 方法名(参数)
抽象为
权限 返回值 | 方法名 | (参数) |
---|---|---|
* | * | (..) |
不难发现*** (..)* 就是所有的方法的表达方式
无论需求是方法 类 还是包
第一个*就代表权限 第二个是路径 第三个是方法,以此类推。
同时一个表达式可以由多个表达式实现,不要拘泥于某个表达方式
以上是关于spring 动态代理开发的切入点表达式的主要内容,如果未能解决你的问题,请参考以下文章