说到spring的ioc,其实就是控制反转,为啥需要控制反转呢,其实是为了功能的增强,如果不用spring, 我们直接使用工厂方法,静态工厂方法, 都是是可以获取到对象的,但是如果需求变了,我们在类的生成时,添加了很多信息,使用工厂就不方便了,还有事务等需要统一的处理.一个典型的应用就是mybatis的接口,平时我们都是只需要写mybatis的接口,但是不写他的实现类,由spring生成一个代理的实现类,来进行方法的调用.对于事务的调用,在service上添加了事务,需要调用dao进行统一的控制.所以需要一个统一的bean对象的管理,就是ioc了,当然了,还可以使用google的juice.
说一点spring3和spring4的区别,spring3提供接口注入.
现在看spring ioc的文档, 5.2版本的文档,现在提供的注入方式有两种,构造方法和set方法注入.
如果使用xml进行配置,在写
说下我们经常使用的@Autowired注解
默认使用的是根据类型注入,如果类型没有找到,就根据属性名在去查找,找不到就报错了.
通过查看spring的源码,当把@Autowired写在属性上的时候,spring是使用的反射,获取该属性的Field,再进行值的设置,完成属性的注入.
@Resource注解可以指定bean的名字和类型,根据属性名注入,跟set方法的名字就没有关系了
最后说一个自定义bean的名字生成策略
BeanNameGenerator 接口
步骤如下:
1.自定义类实现BeanNameGenerator接口,重写方法
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
/**
* 自定义bean name的生成策略
*/
public class MyBeanNameGenerator implements BeanNameGenerator {
@Override
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
String className = definition.getBeanClassName();
System.out.println(className);
int indexOf = className.lastIndexOf(".");
if (indexOf != -1) {
//前面加一个 my,其他的不做处理
return "my"+className.substring(indexOf + 1, className.length());
}
return null;
}
}
2.通过修改@ComponentScan 指定类名生成策略.
@ComponentScan(value = "com.onyx",nameGenerator = MyBeanNameGenerator.class)
再次运行spring就可以看到生成的bean 名字了.
测试代码如下, 就是个main方法:
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
String[] names = context.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
}
如果想要获取到application对象,需要在类上实现接口implements ApplicationContextAware,
在类中定义变量ApplicationContext applicationContext 进行接收, 赋值.就可以使用了.
说一个很特殊的应用场景,在一个类的每个方法中,需要使用的类,每次使用的类都要求是不同的对象,每用一次相当于new 一次, 这个时候需要使用到@LookUp("userDao") 注解,使用的方法上加上,每个方法获取的dao就会一个新的对象,而不是一个单例的dao重用.此注解只能加上方法上.使用方法省略,需要的时候再去具体看吧.
InitializingBean初始化接口
DisposableBean销毁对象的接口
注解:
@PostConstruct
@PreDestroy
一个类实现此接口使用使用到具体的回调方法.也可以使用xml的配置,在
spring还存在@DependsOn 注解, 表明此类的生成需要依赖的其他的一个类的步骤.
@ComponentScan 中可以配置 filter等过滤信息,只扫描需要的类,加快spring的启动速度.里面有一套扫描的形式
还有另外一个方法,添加一个依赖.
这个依赖会加快spring的启动速度.
前段时间做项目,我们项目经理用的eclipse,他启动项目一定要加上@Primary 注解, 否则启动报错,我做的这个项目,我就纳闷了, 我的一个接口就一个实现类,不可能有重名的,不知道eclipse有什么bug,我用idea启动完全没问题.
一个接口,两个实现类,其他地方根据接口注入了,如果不做修改会报错,说找到了两个类.
解决办法 在一个类上标记@Primary 或者使用@Qualifier ,名字做区分.
@Profile
各种环境中类的实例化,类上添加,
激活@Profile.
context.getEnvironment().setActiveProfile("....")
好处就是可以自由的切换类, 配置文件.
spring-jdbc 通用链接,自己做测试用.
spring的循环依赖
修改了application, 之后需要重新reshesh一下.
什么时候用xml
什么时候用注解
什么时候用java config
根据项目来,如果想精通spring,就三者混合这来.
不得不说写总结性的文章真的好要时间,写这个文章的时候,程程刚在睡觉,那时候刚过10点,现在都11点了,只希望疫情能够早点结束,早日能够看到她,我的心情就像外面的濛濛细雨一样,外面的天空是灰蒙蒙的,哎.
科
2020年2月14日11:08:02