Spring自动注入“失效”
来源:互联网 发布:数据库表如何设计null 编辑:程序博客网 时间:2024/05/19 20:57
spring的bean被织入切面后,直接访问他的成员变量,会得到null值。 最糟糕的是不会有任何报错,很难发现。
这个问题的真正原因是,spring的AOP基于动态代理实现,也就是说我们拿到的bean的class不是他本身的class,而是spring自动生成的一个代理对象。
//比如我们有这样一个类public final class HelloMessage { //我们期望这个num被自动注入 @Autowired public Integer num; public String getMessage(){ return "hello world"; }}
它被织入了这样的切面
@Aspectpublic class HelloSpyer { @Pointcut("execution(* hello.HelloMessage.getMessage(..))") public void getMessage(){} @Before("getMessage()") public void Before(){ System.out.println("before"); }}
我们的bean是这样配置的
@Configuration@ComponentScan(basePackages = {"hello"})//这里会scan到HelloMessage,所以下边没有他的@Bean@EnableAspectJAutoProxypublic class HelloConfig { //这里有一个Integer的Bean,按理来说他会被注入HelloClass @Bean public Integer num(){ return new Integer(100); } //这是切面 @Bean public HelloSpyer helloSpyer(){ return new HelloSpyer(); }}
main方法
public class Main { public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(HelloConfig.class); HelloMessage helloMessage = context.getBean(HelloMessage.class); System.out.println(helloMessage.num); System.out.println(helloMessage.getClass()); }}
运行之后,输出:
null
class hello.HelloMessage$$EnhancerBySpringCGLIB$$16ce769e
结果,没有报错,但是num却是null,而且我们发现helloMessge也变成了奇怪的类。具体来说是 CGLIB生成的动态代理。所以访问代理的变量当然是无效的啦。
解决办法也比较简单:
public final class HelloMessage { //我们期望这个num被自动注入 @Autowired public Integer num; public String getMessage(){ return "hello world"; } //增加一个get方法,hh public Integer getNum() { return num; }}
main改为
public class Main { public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(HelloConfig.class); HelloMessage helloMessage = context.getBean(HelloMessage.class); //这里调用方法获得num System.out.println(helloMessage.getNum()); }}
输出:
100
得到了正确的结果。
这告诉我们:
1,不要随便违反迪米特法则,尽量通过接口访问对象
2,spring提倡针对接口编程是有理由的 (hhh)
3,在spring的AOP中,某些有关类型的操作是不可靠的,如类型检查。比如某个业务逻辑要判断
HelloMessage.class == helloMessage.getClass()
会因为spring AOP而得到意想不到的结果
不过
helloMessage instanceof HelloMessageHelloMessage.class.isInstance(helloMessage)
这两种判断是安全的,代理类仍然可以安全转型为其原始类。
另一种解决办法是使用 AspectJ 提供的 AOP ,他提供了一种“编译时增强”的AOP框架,也就是他会修改你的字节码,从而避免了代理类可能带来的错误。而spring的AOP是“运行时增强”。然而大多数时候spring的AOP已经能满足我们的需求了。
0 0
- Spring自动注入“失效”
- Spring自动注入Bean
- Spring自动注入
- Spring的自动注入
- SPRING-MVC 自动注入
- spring 自动依赖注入
- Spring自动注入Bean
- spring 自动扫描 注入
- spring自动注入入门
- spring 自动装配注入
- Spring 自动注入依赖
- Spring自动注入,@Autowired
- Spring自动注入byType
- Spring自动注入construtor
- Spring 自动依赖注入
- spring依赖注入失效的原因之一
- quatz 配置 spring注入失效问题解决办法
- 了解Spring 构造注入和自动注入
- ajax文件上传的思路
- Django配置静态文件的方法
- 【cocos2d-x 3.x 学习与应用总结】4: 使用cocos compile编译apk
- STM32学习堆和栈(三)
- 本文转载自开源中国社区,写的不错,大家可以读一读:block全面分析
- Spring自动注入“失效”
- Android中的NavigationDrawer的分析
- 设计模式六大原则(2):里氏替换原则
- smp_processor_id
- display:inline、block、inline-block和none的区别
- JS使用call函数实现继承
- 一起talk C栗子吧(第一百一十一回:C语言实例--线程间通信)
- POJ 1860(最短路之Bellman-Ford)
- 【转】oracle中rownum和rowid的区别