同一个类下,调用方法,采用AopContext方式,解决Spring注解失效 |
您所在的位置:网站首页 › frameworkcontext › 同一个类下,调用方法,采用AopContext方式,解决Spring注解失效 |
使用:AopContext.currentProxy() 这个解决Spring注解失效 原因简单来说: 同一个类内这样调用的话,只有第一次调用了动态代理生成的ProxyClass,之后一直用的是不带任何切面信息的 知道了原因,处理方法也特别简单只需要显示利用Spring暴露的AopContext即可 解决: ((YourClass) AopContext.currentProxy()).noTransactionTask(keyword);例子: public void noTransactionTask(String keyword){ // 注意这里 调用了代理类的方法 ((YourClass) AopContext.currentProxy()).transactionTask(keyword); } @Transactional void transactionTask(String keyword) { try { Thread.sleep(5000); } catch (InterruptedException e) { //logger //error tracking } System.out.println(keyword); }spring boot注解记得要加上 @EnableAspectJAutoProxy(exposeProxy = true)来暴露AOP的Proxy对象才行,否则会报异常 Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available.注意:exposeProxy = true 是用来暴露AOP的Proxy对象的 产生代理对象就必须要产生一个切面,如果没有,创建代理对象的时候我们会发现对象中的exposeProxy属性还是false,不管你是否设置了exposeProxy = true。 ProxyCreatorSupport的createAopProxy方法: 像@Async这个只是简单的ioc,而没有aop ,创建代理对象的时候我们会发现对象中的exposeProxy属性总是false 而@Transactional 会将类定义成是一个切面。所以我们可以用 AopContext.currentProxy() 来解决同一个类下,调用方法事务的问题 例子: @Async 想要用 AopContext.currentProxy() 最简单的方法就是在被调用方法上添加一个事务的注解 @Transactional : @Transactional @Async void transactionTask(String keyword) { try { Thread.sleep(5000); } catch (InterruptedException e) { //logger //error tracking } System.out.println(keyword); }其实以上通过 AopContext.currentProxy() 这个方法去解决Spring注解失效的问题不是好的方案 更为简单的解决方案: 1.将被调用方法放到另一个类中 2.@Autowired注解让spring自动注入ApplicationContext,通过applicationContext.getBean(YourClass.class)获取类,然后调用你的方法 /** * 注解让spring自动注入ApplicationContext */ @Autowired private ApplicationContext applicationContext;3.web项目可以通过WebApplicationContext 获取Spring容器上下文,通过wac.getBean(YourClass.class)获取类,然后调用你的方法 WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext(); 或者 (通过request或session加载spring容器) WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext()); 或者 ServletContext application = ServletActionContext.getServletContext(); ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(application);4.写一个工具类获取Spring 的bean,然后通过 SpringContextUtil去获取类,然后调用你的方法 SpringContextUtil.getBean(YourClass.class) import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; /** * Created by qinjp on 2018/3/28. */ @Component public class SpringContextUtil implements ApplicationContextAware { private static ApplicationContext applicationContext; @Autowired @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { SpringContextUtil.applicationContext = applicationContext; } public static T getBean(Class clazz){ return applicationContext.getBean(clazz); } public static T getBean(String name, Class requiredType) { return applicationContext.getBean(name, requiredType); } }5.通过ApplicationListener获取spring 的上下文容器 ,获取类,然后调用你的方法 @Component // 注入spring容器 public class SpringManager implements ApplicationListener { private static ApplicationContext applicationContext = null; @Override public void onApplicationEvent(ContextRefreshedEvent event) { if(applicationContext == null){ applicationContext = event.getApplicationContext(); } } public static ApplicationContext getApplicationContext() { return applicationContext; } public static T getBean(Class clazz){ return applicationContext.getBean(clazz); } }6.spring boot 通过入口main函数获取spring 的上下文容器 ,获取类,然后调用你的方法 public static void main(String[] args) { ApplicationContext context = SpringApplication.run(Application.class, args); SpringContextUtil.setApplicationContext(context); } import org.springframework.context.ApplicationContext; public class SpringContextUtil { private static ApplicationContext applicationContext; public static ApplicationContext getApplicationContext(){ return applicationContext; } public static void setApplicationContext(ApplicationContext applicationContext){ SpringContextUtil.applicationContext = applicationContext; } public static T getBean(String name){ return (T)applicationContext.getBean(name); } public static T getBean(Class clazz){ return applicationContext.getBean(clazz); } } |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |