Spring AOP获取不了增强类(额外方法)和无法通过getBean()获取对象
今天在学习AOP发现一个小问题
Spring AOP获取不了额外方法,左思右想发现是接口上出了问题
先上代码
获取不了增强类
UserService接口
public interface UserService {
public void register(User user);
public Boolean login(String name, String password);
}
接口实现UserServiceImpl(原始方法)
这是出问题的地方
import org.User;
import org.aopalliance.aop.Advice;
public class UserServiceImpl implements UserService , Advice{
@Override
public void register(User user) {
System.out.println("UserServiceImpl.register");
}
@Override
public Boolean login(String name, String password) {
System.out.println("UserServiceImpl.login "+name+" "+password );
return true;
}
}
增强类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");
}
}
接着执行业务代码A
@Test
public void test2() {
ApplicationContext context=new ClassPathXmlApplicationContext("/ApplicationContext2.XML");
UserServiceImpl userService= (UserServiceImpl) context.getBean("UserServicePiont");
userService.login("SY", "123456");
userService.register(new User());
}
}
就发现额外方法没有执行
输出是这样的
2021-05-24 20:51:36 DEBUG DefaultListableBeanFactory:225 - Creating shared instance of singleton bean 'org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor#0'
UserServiceImpl.login SY 123456
UserServiceImpl.register
并没有输出预期的UserPoxyBefore.before
检查发现不知在UserServiceImpl处添加进入了Advice接口,Advice接口本身没有任何方法,难以发现
去掉即可
结果如下
UserPoxyBefore.before
UserServiceImpl.login SY 123456
UserPoxyBefore.before
UserServiceImpl.register
正确执行
总结:在组装好切点和指定好切面方法之后发现,没有执行,则需要检查接口是否为原始类所implements的接口
也算是一点小坑吧
无法通过getBean()
这个是在总结获取不了增强类时发现的,给自己打个预防针
在获取对象时,由于已经做了组装好切点和指定好切面方法,所以Spring获取的应该是代理对象而非原始对象所以在业务中使用原始对象获取Bean肯定会出问题
具体如下
业务代码B
@Test
public void test2() {
ApplicationContext context=new ClassPathXmlApplicationContext("/ApplicationContext2.XML");
UserServiceImpl userService= (UserServiceImpl) context.getBean("UserServicePiont");
userService.login("SY", "123456");
userService.register(new User());
}
从之前的代码可以知道UserServiceImpl是原始代码
我尝试执行下出如下结果
java.lang.ClassCastException: com.sun.proxy.$Proxy6 cannot be cast to org.Service.UserServiceImpl
说com.sun.proxy.$Proxy6不能变为org.Service.UserServiceImpl
由此看出spring代理的对象早已不是原来的对象了
在搜索了其他人的分析发现
aop切面插入后该bean被jdk内部自动转为了com.sun.proxy.$Proxy25类型类型已被转变,所以无法通过类UserServiceImpl进行获取
那么如何获取后如何执行该类的代理方法呢?
很简单 使用原始类所implements的接口即可如上面业务代码A那样即可
有人问获取后如何执行该原始类的方法呢?
好像使用反射可以达到目的,在此不再研究,具体生产环境遇到再说,继续学习。