由于准备着手研究一下Spring Boot 和Spring Cloud,所以抽空把Spring对Bean的装配和Spring容器的依赖注入重新整理了一下,理解了一下内在本质!
今天主要整理的是基于注解的方式对Bean的管理,下面是具体的Demo!
org.springframework
spring-context
4.3.9.RELEASE
javax.inject
javax.inject
1
//通过加入组建
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class, User.class, UserDao.class,UserService.class,UserController.class);
//通过扫描包
//AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext("com.harry.**");
package com.harry.spring4.demo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Scope;
/**
* Bean的配置类,类似于applicationContext.xml里配置的各种Bean
*
* @author Harry Wan
*
*/
@Configuration
public class MyConfig {
/**
* 表示配置了一个Bean,name默认为方法名 "createMyBean"
*
* @return
*/
@Bean
@Scope(scopeName = "prototype")
public MyBean createMyBean() {
return new MyBean();
}
/**
* 自定义Bean的name,从容器中获取时按定义的名称获取
*
* @return
*/
@Bean(name = "myBean")
@Scope(scopeName = "prototype")
public MyBean createMyBeanWithRename() {
return new MyBean();
}
@Bean
public MyFactoryBean createMyFactoryBean() {
return new MyFactoryBean();
}
@Bean
public MyCustomFactory createMyCustomFactory() {
return new MyCustomFactory();
}
@Bean
public MyBean createMyBeanByCustomFactory(MyCustomFactory factory) {
return factory.createMyBean();
}
@Bean
public MyBean2 createMyBean2ByCustomFactory(MyCustomFactory factory) {
return factory.createMyBean2();
}
@Bean
public MyBean3 createMyBean3() {
return new MyBean3();
}
@Bean(initMethod = "init", destroyMethod = "destroy")
public MyBean4 createMyBean4() {
return new MyBean4();
}
@Bean
public MyBean5 createMyBean5() {
return new MyBean5();
}
@Bean
//@Primary
public UserDao createUserDao(){
return new UserDao();
}
}
/**第一种方式: 通过自定义创建实例化Bean,交给Spring来管理**/
//从容器中通过类型来获取.
//注: 若容器中有多个实例化Bean的方法,此时通过类型来获取,会Bean匹配错误
//System.out.println(applicationContext.getBean(MyBean.class));
//从容器中通过名称来获取
System.out.println(applicationContext.getBean("createMyBean"));
System.out.println(applicationContext.getBean("myBean"));
/**
* 表示配置了一个Bean,name默认为方法名 "createMyBean"
*
* @return
*/
@Bean
@Scope(scopeName = "prototype")
public MyBean createMyBean() {
return new MyBean();
}
/**
* 自定义Bean的name,从容器中获取时按定义的名称获取
*
* @return
*/
@Bean(name = "myBean")
@Scope(scopeName = "prototype")
public MyBean createMyBeanWithRename() {
return new MyBean();
}
/** 第二种方式: 通过BeanFactory来创建实例化Bean**/
//通过类型获取FactoryBean创建的Bean的实例对象
//System.out.println(applicationContext.getBean(MyBean2.class));
//通过名字来获取FactoryBean创建的Bean的实例对象
System.out.println(applicationContext.getBean("createMyFactoryBean"));
//通过类型获取到的是MyFactoryBean本身,并非MyFactoryBean创建出来的Bean
System.out.println(applicationContext.getBean(MyFactoryBean.class));
//通过名称获取到的是MyFactoryBean本身,并非MyFactoryBean创建出来的Bean
System.out.println(applicationContext.getBean("&createMyFactoryBean"));
package com.harry.spring4.demo;
import org.springframework.beans.factory.FactoryBean;
/**
* 通过FactoryBean 来创建对象
* @author Harry Wan
*
*/
public class MyFactoryBean implements FactoryBean {
//获取到FactoryBean所创建的实力对象
public MyBean2 getObject() throws Exception {
return new MyBean2();
}
//获取Bean的类型
public Class> getObjectType() {
return MyBean2.class;
}
public boolean isSingleton() {
return true;
}
}
/** 第三种方式: 通过自定义Factory来创建Bean实例,把自定义的Factory也当作Bean交给Spring来管理 **/
//可以通过类型来获取MyBean.class,为了避免通过类型匹配到多个实例化Bean的方法,改为通过Name来获取
System.out.println(applicationContext.getBean("createMyBeanByCustomFactory"));
System.out.println(applicationContext.getBean("createMyBean2ByCustomFactory"));
package com.harry.spring4.demo;
public class MyCustomFactory {
public MyBean createMyBean() {
return new MyBean();
}
public MyBean2 createMyBean2() {
return new MyBean2();
}
}
@Bean
public MyCustomFactory createMyCustomFactory() {
return new MyCustomFactory();
}
@Bean
public MyBean createMyBeanByCustomFactory(MyCustomFactory factory) {
return factory.createMyBean();
}
@Bean
public MyBean2 createMyBean2ByCustomFactory(MyCustomFactory factory) {
return factory.createMyBean2();
}
/**第四种方式: 通过使用@Component组件相关注解,交给Spring容器装配**/
//注: 实际开发中通常使用scan扫描包自动加入Spring容器(new AnnotationConfigApplicationContext("com.harry.**");),如若其他方式要手动加入到Spring容器中
System.out.println(applicationContext.getBeansOfType(User.class));//获取Spring容器管理Bean时该Bean使用的默认名称(Map: 名称 = 实例化对象)
//@Component
System.out.println(applicationContext.getBean(User.class));
System.out.println(applicationContext.getBean("myUser"));
//@Repository
System.out.println(applicationContext.getBean(UserDao.class));
//@Service
System.out.println(applicationContext.getBean(UserService.class));
//@Controller
System.out.println(applicationContext.getBean(UserController.class));
注:通过使用@Component等注解表示当前类为Spring的组建,Spring默认进行装配进行管理,这也是实际开发中用的最多的方式
/**第一种方式: 目标Bean实现InitializingBean, DisposableBean接口,实现对应的afterPropertiesSet()和destroy()方法**/
System.out.println(applicationContext.getBean("createMyBean3"));
package com.harry.spring4.demo;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
public class MyBean3 implements InitializingBean, DisposableBean {
/**
* 当Bean被Spring加载之后会执行
*/
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("==It will be executed after being Loaded==");
}
/**
* 当Bean销毁之后会执行
*/
@Override
public void destroy() throws Exception {
System.out.println("==It will be executed after being Destroyed==");
}
}
/**第二种方式: 在注解@Bean是指定(initMethod = "init", destroyMethod = "destroy")**/
System.out.println(applicationContext.getBean("createMyBean4"));
配置类:
@Bean(initMethod = "init", destroyMethod = "destroy")
public MyBean4 createMyBean4() {
return new MyBean4();
}
package com.harry.spring4.demo;
public class MyBean4 {
/**
* 当Bean被Spring加载之后会执行
*/
public void init() {
System.out.println("==It will be executed after being Loaded==");
}
/**
* 当Bean销毁之后会执行
*/
public void destroy(){
System.out.println("==It will be executed after being Destroyed==");
}
}
/**第三种方式: 通过Javax(JSR-250)注解@PostConstruct和@PreDestroy方式**/
System.out.println(applicationContext.getBean("createMyBean5"));
目标Bean:
package com.harry.spring4.demo;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
public class MyBean5 {
/**
* 当Bean被Spring加载之后会执行
*/
@PostConstruct
public void init() {
System.out.println("==It will be executed after being Loaded==");
}
/**
* 当Bean销毁之后会执行
*/
@PreDestroy
public void destroy(){
System.out.println("==It will be executed after being Destroyed==");
}
}
package com.harry.spring4.demo;
import javax.annotation.Resource;
import javax.inject.Inject;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Repository;
/**
* Spring 依赖注入
* @author Harry Wan
*
*/
public class MyDemo2 {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext("com.harry.**");
//使用@Repository注解装配
System.out.println(applicationContext.getBean("userDao"));
//使用@Bean 自定义实例化对象装配
System.out.println(applicationContext.getBean("createUserDao"));
/**注入的三种方式**/
//@Autowired 依赖 UserDao ---Spring提供的注入方式,可以指定具体装配哪一个
//@Resource 依赖User ----JSR-250提供的注入方式(JDK自带)
//@Inject 依赖MyBean ----JSR-330提供的注入方式(需要添加依赖)
UserService userService = applicationContext.getBean(UserService.class);
//在有多个实例化Bean的情况下,默认情况下,Spring优先会注入@Repository注解的组建Bean,
//可以在@Autowired下使用@Qualifier(value = "createUserDao")或者在@Bean下使用@Primary来指定装配哪一个
System.out.println(userService);
applicationContext.close();
}
}
package com.harry.spring4.demo;
import javax.annotation.Resource;
import javax.inject.Inject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
@Qualifier(value="createUserDao")
private UserDao userDao;
//JSR-250提供的注入方式(JDK自带)
@Resource
private User user;
//JSR-330提供的注入方式(需要添加依赖)
@Inject
private MyBean myBean;
@Override
public String toString() {
return "UserService [userDao=" + userDao + ", user=" + user + ", myBean=" + myBean + "]";
}
}
@Bean
//@Primary
public UserDao createUserDao(){
return new UserDao();
}
package com.harry.spring4.demo;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.stereotype.Service;
public class MyDemo3 {
public static void main(String[] args) {
/**
* 把扫描包的注解配置信息添加在AnnotationScanConfig中,通过Spring容器读取配置文件的方式加载扫描配置
* @ComponentScan(basePackages="com.harry.**",excludeFilters=@Filter(type=FilterType.ASSIGNABLE_TYPE,classes={UserService.class,MyConfig.class}))
* 排除用@Service注解的UserService和在MyConfig中自定义配置的Bean的扫描
*
* 如若使用@Component注解注释的Bean,可直接排除
* 如若使用Config配置文件自定义实例化Bean的方式,不能直接排除Bean的本身,要填写Config配置类,从而来排除配置文件中配置的Bean
*
*/
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AnnotationScanConfig.class);
System.out.println(applicationContext.getBean(User.class));
System.out.println(applicationContext.getBean(UserService.class));
System.out.println(applicationContext.getBean(MyBean.class));
applicationContext.close();
}
}
package com.harry.spring4.demo;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
@Configuration
@ComponentScan(basePackages="com.harry.**",excludeFilters=@Filter(type=FilterType.ASSIGNABLE_TYPE,classes={UserService.class,MyConfig.class}))
public class AnnotationScanConfig {
}