java是一门面向对象的语言,当我们在web开发时经常会使用到三层架构的模型(dao,service,controller),我们通常会在controller中调用service,service中调用dao,在没有用到spring框架时,我们会通过手动new的方式创建对象去进行相互的调用。spring可以做到bean对象的统一管理,当我们使用对象时不用通过new的方式,只需要在容器里面去拿就好了,spring注册bean可以通过文件xml的形式,也可以通过注解的形式,本文主要分享关于bean注解的相关使用。
目录
-
@Configuration + @Bean
-
@ComponentScan
-
@Scope + @Lazy
-
@Conditional
-
@Profile
-
@Import
-
FactoryBean
1.@Configuration + @Bean
Configuration主要标记这是一个配置类,@Bean主要用于注册bean对象
比如说我想要去注册一个角色对象,可以通过@Bean把它交给spring去管理,在使用的时候可以直接拿来使用,拿的时候可以通过类名,也可以通过方法名
@Configuration
public class MyConfig {
@Bean(name="role")
public Role role(){
return new Role(001,"ASen","高富帅");
}
}
public class Test {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
Role bean = (Role) context.getBean(Role.class);
// Role bean = (Role) context.getBean("role");
System.out.println(bean);
}
}
//结果 : Role{role_id=1, role_name='ASen', role_desc='高富帅'}
2.@ComponentScan
@ComponentScan是一个扫描注解,它指定我们需要扫描的包,以及可以指定我们想要的过滤规则(过滤可自行测试),可以扫描到被spring管理的类(如@Controller @Service @Component @Repository
等注解下的类),如下RoleSevice和RoleController都被注解修饰,我们可以拿到所有的bean名称
@Configuration
@ComponentScan("com.senge")
public class MyConfig {
@Bean
public Role role(){
return new Role(001,"ASen","高富帅");
}
}
@Controller
public class RoleController {
}
@Service
public class RoleService {
}
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
String[] beanDefinitionNames = context.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
}
//测试结果
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
myConfig
roleController
roleService
role
3.@Scope + @Lazy
我们用@bean注入的对象默认是单列的,使用@Scope注解可以设置bean的作用域(设置单例的时候会在容器启动的时候创建对象,多例会在调用的时候创建对象),如果在使用单列时,不想在容器启动的时候就创建对象可以使用@Lazy(懒加载)注解,这样会在使用对象的时候创建
public class MyConfig {
@Bean
@Scope(value = "singleton") //prototype request session
public Role role(){
return new Role(001,"ASen","高富帅");
}
}
public class Test2 {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
Role bean1 = (Role) context.getBean(Role.class);
Role bean2 = (Role) context.getBean(Role.class);
System.out.println(bean1==bean2);
}
}
//测试结果(多例可自行测试)
true
4.@Conditional
@Conditional是一个条件注解,它会根据我们定义的条件去判断是否注入bean
@Configuration
public class JavaConfig {
@Bean
@Conditional(value = {MyCondition.class})
public Role role(){
return new Role(002,"ASen","高富帅");
}
}
public class MyCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//根据需要写条件,返回false则无法注入
return false;
}
}
5.@Profile
@Profile和@Bean一起用,可来指明在什么环境下注册bean
@Configuration
public class JavaConfig {
@Bean
@Profile("dev")
Role devRole(){
return new Role(001,"dev","123456");
}
@Bean
@Profile("pro")
Role proRole(){
return new Role(001,"pro","123456");
}
}
public class Test4 {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.getEnvironment().setActiveProfiles("pro");
context.register(JavaConfig.class);
context.refresh();
Role bean = context.getBean(Role.class);
System.out.println(bean);
}
}
//测试结果 Role{role_id=1, role_name='pro', role_desc='123456'}
6.@Import
@Import可以快速注入bean,案例中注入Student对象
@Configuration
@Import({Student.class})
public class MyConfig {
}
public class Test {
public static void main(String[] args) {
ApplicationContext ac = new AnnotationConfigApplicationContext(MyConfig.class);
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
}
}
//测试结果
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
myConfig
com.senge.ioc.beans.Student
@Import也可以通过ImportSelector自定义注册bean
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
//annotationMetadata 是@Import标记的类的注解信息
return new String[]{"com.senge.ioc.beans.User"};
}
}
@Configuration
@Import({Student.class,MyImportSelector.class})
public class MyConfig {
}
public class Test {
public static void main(String[] args) {
ApplicationContext ac = new AnnotationConfigApplicationContext(MyConfig.class);
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
}
}
//测试结果
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
myConfig
com.senge.ioc.beans.Student
com.senge.ioc.beans.User
@Import通过ImportBeanDefinitionRegistrar手动注册bean
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Role.class);
beanDefinitionRegistry.registerBeanDefinition("Role",rootBeanDefinition);
}
}
@Configuration
@Import({Student.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})
public class MyConfig {
}
测试就可以发现Role被注册到容器中了
7.FactoryBean
除了上述注解外,我们可以通过工厂类FactoryBean注册
public class MyFactoryBean implements FactoryBean {
@Override
public Object getObject() throws Exception {
return new Book();
}
@Override
public Class<?> getObjectType() {
return Book.class;
}
@Override
public boolean isSingleton() {
return true;//是否单列
}
}
@Configuration
@Import({Student.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})
public class MyConfig {
@Bean
public MyFactoryBean myFactoryBean(){
return new MyFactoryBean();
}
}
public class Test {
public static void main(String[] args) {
ApplicationContext ac = new AnnotationConfigApplicationContext(MyConfig.class);
Object myFactoryBean1 = ac.getBean("myFactoryBean");
System.out.println(myFactoryBean1.getClass());
Object myFactoryBean2 = ac.getBean("&myFactoryBean");//获取本身类
System.out.println(myFactoryBean2.getClass());
}
}
//测试结果
class com.senge.ioc.beans.Book
class com.senge.ioc.config.MyFactoryBean