9. 由Spring管理的对象的生命周期
如果需要管理Bean的生命周期,可以在对应的类中自定义生命周期的初始化方法和销毁方法,关于这2个方法的声明:
应该使用public权限;
使用void表示返回值类型;
方法名称可以自定义;
参数列表为空。
例如:
package cn.tedu.spring; public class User { public User() { System.out.println("User.User()"); } public void init() { System.out.println("User.init()"); } public void destroy() { System.out.println("User.destroy()"); } }
在配置Spring管理对象的@Bean注解中,配置注解参数,以指定以上2个方法分别是初始化方法和销毁方法:
package cn.tedu.spring; @Configuration public class BeanFactory { @Bean(initMethod = "init", destroyMethod = "destroy") public User user() { return new User(); } }
最终,可以看到:
初始化方法会在构造方法之后执行,且只执行1次;
销毁方法会在Spring容器被销毁之前执行,且只执行1次。
10. 使用组件扫描使得Spring管理类的对象
首先,自定义某个类(类名、包名均没有要求),在类的声明之前添加@ComponentScan注解,该注解用于配置组件扫描,注解的参数是String类型的,表示“被扫描的根包”:
package cn.tedu.spring; import org.springframework.context.annotation.ComponentScan; @ComponentScan("cn.tedu.spring") public class SpringConfig { }
在组件扫描的包下创建类,该类的声明之前需要添加@Component注解,以表示这个类是一个“组件类”,后续,当Spring扫描时,会自动创建所有组件类的对象:
package cn.tedu.spring; import org.springframework.stereotype.Component; @Component public class User { }
当完成以后配置后,后续,程序执行时,只要加载了SpringConfig类,由于类之前配置了组件扫描,Spring框架就会扫描对应的包下所有的类,并逐一检查是否为“组件类”,如果是,则创建对象,如果不是,则不创建!
使用@ComponentScan时,配置的是需要扫描的“根包”,假设需要扫描的是cn.tedu.spring,在配置时,配置为cn.tedu甚至配置为cn都是可用的,但是,强烈不推荐使用过于简单的设置,避免出现扫描范围过多而导致的浪费资源!
另外,在@ComponentScan注解的源代码中:
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented @Repeatable(ComponentScans.class) public @interface ComponentScan { @AliasFor("basePackages") String[] value() default {}; @AliasFor("value") String[] basePackages() default {}; }
可以看出,配置的值可以是String[],也就是可以指定多个包名。
在使用这种做法时,必须保证被Spring管理的对象所归属的类存在无参数构造方法!
在使用这种做法时,Spring创建对象后,默认会使用以下原则作为Bean的名称:
如果类名的第1个字母是大写的,第2个字母是小写的(不关心其它字母的大小写),则会把类名的第1个字母改为小写,其它不变,作为Bean的名称,例如类名是User时,Bean的名称就是user,类名是UserDao时,Bean的名称就是userDao;
如果不满足以上条件,则类名就是Bean的名称。
如果希望使用自定义的名称作为Bean的名称,可以在@Component注解中配置参数,例如:
package cn.tedu.spring; import org.springframework.stereotype.Component; @Component("uuu") public class User { }
则后续调用getBean()方法时,就必须使用"uuu"作为参数来获取对象!
在Spring框架的作用范围内,除了@Component以外,另外还有3个注解,可以起到完全等效的效果:
@Controller:通常添加在控制器类的声明之前;
@Service:通常添加在业务类的声明之前;
@Repository:通常添加在持久层的类(负责数据的持久化管理)的声明之前。
也就是说,这4种注解作用、用法完全相同,只是语义不同。
目前,已经介绍了2种使得Spring框架管理类的对象的做法:
自定义方法返回某个对象,并在方法的声明之前添加@Bean注解;
将类放在组件扫描的包或其子孙包中,并在类的声明之前添加@Component/@Controller/@Service/@Repository注解。
以上的第1种做法是万能的,适用于任何条件,但是,在设计代码时相对麻烦,管理起来相对不便利;而第2种做法就更加简单、直观,却只适用于自定义的类。
所以,只要是自行编写的类,都应该采取第2种做法,如果需要Spring管理其它类(JDK中的,或某框架中的)的对象,只能使用第1种做法!
11. 使用Spring读取.properties文件
假设在项目的src/main/resources下存在jdbc.properties文件,其内容是:
url=jdbc:mysql://localhost:3306/db_name
driver=com.mysql.jdbc.Driver
然后,在项目中,自定义某个类,在这个类中,声明对应数量的属性,这些属性的值将会是以上配置信息的值!
public class JdbcProperties { private String url; private String driver; // 生成以上2个属性的Getters & Setters }
当需要读取以上jdbc.properties配置文件时,需要在以上类的声明之前添加@PropertySource注解,并配置需要读取的文件的位置:
// 以下注解的参数是配置文件的名称 @PropertySource("jdbc.properties") public class JdbcProperties { private String url; private String driver; // 生成以上2个属性的Getters & Setters }