基于注解定义BeanDefinition
1、概述
JavaConfig spring3.0开始使用 spring4.0成为核心普通的Java pojo只要标注
上注解@Configuration,就可以为spring容器提供bean的定义信息,每个
@Bean标注的函数都相当于提供一个Bean的定义信息。
2、@Configuration使用方式一@Bean
@Configuration
public class BeanConfig {
//如果没有配置name属性,则bean name 默认等于函数名称!!!!
@Bean(name=”boss”)
public Boss boss(){
Boss boss = new Boss();
return boss;
}
}
3、@Configuration使用方式二调用@Bean标注的方法
调用@Bean标注的方法其实就相当于从容器中获取已经实例化的userDao bean。
public class RoleDao {
}
public class UserDao {
}
public class LoginService {
private UserDao userDao;
private RoleDao roleDao;
public void init11(){
System.out.println("init111");
}
Get Set 函数省略
}
@Configuration
public class AppConfig {
@Bean
public UserDao userDao(){
UserDao userDao = new UserDao();
System.out.println(userDao);
return userDao;
}
@Bean
public RoleDao roleDao(){
RoleDao roleDao = new RoleDao();
System.out.println(roleDao);
return roleDao;
}
@Bean(initMethod = "init11")
public LoginService loginService(){
LoginService loginService = new LoginService();
UserDao userDao = userDao(); //调用@Bean标注的方法其实就相当于从容器中获取已经实例化的userDao bean。
RoleDao roleDao = roleDao();
System.out.println("loginService userDao :" + userDao);
System.out.println("loginService roleDao:" + roleDao);
loginService.setUserDao(userDao);
loginService.setRoleDao(roleDao);
return loginService;
}
}
方式二的配置等价于如下xml配置:
<bean id="userDao" class="com.wzy.springstudy.javaconfig.dao.UserDao"/>
<bean id="roleDao" class="com.wzy.springstudy.javaconfig.dao.RoleDao"/>
<bean id="loginService" class="com.wzy.springstudy.javaconfig.service.LoginService"
p:roleDao-ref="roleDao"
p:userDao-ref="userDao"/>
测试代码:
@Test
public void testAnnotationApplicationContext(){
ApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
//除了使用配置类来加载应用上下文,也可以使用包扫描来加载。
//ApplicationContext context1 = new AnnotationConfigApplicationContext("com.wzy");
LoginService bean = context.getBean(LoginService.class);
System.out.println(bean);
}
测试代码输出如下:
com.wzy.springstudy.javaconfig.dao.UserDao@2d2e5f00
com.wzy.springstudy.javaconfig.dao.RoleDao@4c40b76e
loginService userDao :com.wzy.springstudy.javaconfig.dao.UserDao@2d2e5f00
loginService roleDao:com.wzy.springstudy.javaconfig.dao.RoleDao@4c40b76e
com.wzy.springstudy.javaconfig.service.LoginService@5ef60048
由上面可以看出加载是先加载userDao + roleDao 两个bean,然后再加载loginService bean, 而且调用@Bean标注的方法其实就相当于从容器中获取已经实例化的userDao bean。
4、@Configuration使用方式三注入其他标记此注解的类
@Configuration注解本身就标记了@Component注解,因此它也可以注入
其他的类,比如注入被@Configuration注解标注的类,在调用注入的
@Configuration标注的类的@Bean标注的方法的时候,不是简单的执行方
法逻辑而已,而是从spring容器中返回相应的bean,这需要归功于
springAOP, 所以这样配置的时候一定要保证springAOP的包和CGLIB的包
有依赖。
public class RoleDao {
}
public class UserDao {
}
public class LoginService {
private UserDao userDao;
private RoleDao roleDao;
Get Set 函数省略
}
@Configuration
public class DaoConfig {
@Bean
public UserDao userDao(){
UserDao userDao = new UserDao();
System.out.println(userDao);
return userDao;
}
@Bean
public RoleDao roleDao(){
RoleDao roleDao = new RoleDao();
System.out.println(roleDao);
return roleDao;
}
}
@Configuration
public class AppConfig {
@Autowired
private DaoConfig daoConfig;
@Bean
public LoginService loginService(){
LoginService loginService = new LoginService();
UserDao userDao = daoConfig.userDao();
RoleDao roleDao = daoConfig.roleDao();
/*daoConfig.userDao() 方法就相当于将DaoConfig中定义的Bean注入进来,这个功
能是需要spring aop支持的,因为在调用daoConfig.userDao()方法的时候,不是简
单的执行方法逻辑而已,而是从spring容器中返回相应的bean,这需要归功于
springaop 所以这样配置一定要保证springaop的包和CGLIB的包有依赖。也就是说
只要bean的作用域是单例,不管调用多少次daoConfig.userDao()方法返回的都是同
一个bean,如果bean的作用域为prototype的话,将会返回不同的bena。比如:
@Bean
@Scope("prototype")
public UserDao userDao(){
return new UserDao();
}
*/
System.out.println("loginService userDao :" + userDao);
System.out.println("loginService roleDao:" + roleDao);
loginService.setUserDao(userDao);
loginService.setRoleDao(roleDao);
return loginService;
}
}
5、JavaConfig配置BeanDefinition时启动spring容器的方式
5.1、指定JavaConfig类启动容器
@Test
public void testAnnotationApplicationContext(){
ApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
LoginService bean = context.getBean(LoginService.class);
System.out.println(bean);
}
5.2、指定JavaConfig配置包启动容器
@Test
public void testAnnotationApplicationContext(){
ApplicationContext context =
new AnnotationConfigApplicationContext("com.wzy.javaconfig.conf");
LoginService bean = context.getBean(LoginService.class);
System.out.println(bean);
}
5.3、使用ApplicationContext.register()注册配置类启动容器
@Test
public void testAnnotationApplicationContext(){
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext();
context.register(AppConfig.class);
context.register(DaoConfig.class);
context.refresh();
LoginService bean = context.getBean(LoginService.class);
System.out.println(bean);
}
5.4、@Import
除了一个一个注册外,还可以使用@Import注解将多个配置组装到一个配置中
如下使用:
@Configuration
public class DaoConfig {
@Bean
@Scope("prototype")
public UserDao userDao(){
UserDao userDao = new UserDao();
System.out.println(userDao);
return userDao;
}
@Bean
public RoleDao roleDao(){
RoleDao roleDao = new RoleDao();
System.out.println(roleDao);
return roleDao;
}
}
@Configuration
@Import(DaoConfig.class)
@ImportResource("classpath:spring-context.xml")
public class AppConfig {
@Bean
@Autowired
public LoginService loginService(UserDao userDao, RoleDao roleDao, Dog dog){
LoginService loginService = new LoginService();
loginService.setUserDao(userDao);
loginService.setRoleDao(roleDao);
System.out.println(dog.getName());
return loginService;
}
}
5.5、@ImportResource
除此之外@ImportResource("classpath:spring-context.xml")表示将
classpath:spring-context.xml里的bean 定义导入到AppConfig 类中来。