@Bean注解详解 Posted 2023-04-04 怪 咖@
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了@Bean注解详解相关的知识,希望对你有一定的参考价值。
作用: 用于将对象存入spring的ioc容器中,同@controller、@Service、@Component、@Configuration、@Repository
等几个注解是一样的,都是负责将对象存入容器当中
。只不过方式不同,他们是用在类上面的,然后将当前类通过无参构造函数创建对象
然后放入容器,而@Bean
是用在方法上,将当前方法的返回值对象
放到容器当中!可以理解为前者是由spring自动创建对象,而@Bean创建对象是交给我们自己来控制。使用位置: @Bean一般出现在方法
上面,也可用于自定义注解
上。修饰的方法的位置: 使用@Bean修饰的方法,可以放在@controller、@Service、@Component、@Configuration、@Repository
修饰的类当中,这样项目在启动的时候,@Bean方法返回的对象也会立马存入容器当中!放在启动类也是可以的哦!光通过@Bean
是无法将对象放入容器当中的!对象名: 默认注入到容器当中的对象id(有的也叫做名称)是方法名
,但是如果需要显式命名,则可以在注解上使用 name 属性(或其别名value)。比如:@Bean(name = "名称")
或者@Bean("名称")
,当然也可以有多个名称@Bean(name = "dataSource1", "dataSource2", "dataSource3" )
所属: @Bean属于spring当中的注解,在spring-context包下,而并非springboot!对方法的要求: 可以使用static final修饰、但是有个前提方法一定要有返回值,否则启动报错!@controller、@Service、@Configuration、@Repository
这四个注解其实都是@Component
派生注解,点开源码就会发现,全是使用的@Component注解自定义的。其实spring整这几个注解就是为了方便我们分层,controller层用@controller,service用@Service,仅此而已!
(1)定义bean
@Configuration
public class Myconfig
@Bean
public User user01 ( )
User user = new User ( ) ;
return user;
@controller、@Service、@Component、@Configuration、@Repository
这些注解就等同于之前在xml里的配置
< beans>
< bean id = " user01" class = " com.gzl.cn.User" />
</ beans>
而@Bean
注解有点像xml当中通过factory-method指定类当中的方法创建bean,如下使用工厂中的静态方法创建对象
public class StaticFactory
public static IAccountService getAccountService ( )
return new AccountServiceImpl ( ) ;
< bean id = " accountService" class = " com.gzl.factory.StaticFactory" factory-method = " getAccountService" > </ bean>
xml当中还有另一种,普通方法创建对象
public class InstanceFactory
public IAccountService getAccountService ( )
return new AccountServiceImpl ( ) ;
< bean id = " instanceFactory" class = " com.gzl.factory.InstanceFactory" > </ bean>
< bean id = " accountService" factory-bean = " instanceFactory" factory-method = " getAccountService" > </ bean>
(2) 怎么看注入到容器当中的id呢
springboot项目的话直接通过启动类获取ioc容器,然后通过容器提供的方法就可以获取到容器当中的对象,注意是在项目启动的时候获取的哦!当然除此方式之外还有其他方式可以获取到ioc容器,本篇就不过多讲解了。
@SpringBootApplication
public class SpringBootCacheApplication
public static void main ( String [ ] args)
ConfigurableApplicationContext run =
SpringApplication . run ( SpringBootCacheApplication . class , args) ;
String [ ] userBeanNames = run. getBeanNamesForType ( User . class ) ;
for ( String s : userBeanNames)
System . out. println ( "---user:" + s) ;
boolean b = run. containsBean ( "user01" ) ;
System . out. println ( b) ;
User bean = run. getBean ( User . class ) ;
System . out. println ( bean) ;
(3)依赖注入
@Bean
也可以依赖其他任意数量的bean,如下示例:创建User 对象的时候,需要使用到Student ,而Student 恰好也在容器当中,那我们就不需要在user01方法中创建了,直接从容器里面获取即可,@Bean可以通过方法参数实现依赖注入
,在执行user01方法的时候,spring会根据参数名称先去容器当中找Student 对象,找不到根据对象的class类型找,有点类似于@Resource注解(先根据名称,再根据类型),如果找到直接以参数形式传给user01方法, 如果没找到,启动项目直接会报could not be found
异常!
@Configuration
public class Myconfig
@Bean
public User user01 ( Student student)
User user = new User ( ) ;
user. setName ( student. getName ( ) ) ;
return user;
(4)接受生命周期的回调
任何使用@Bean定义的bean,也可以执行生命周期的回调函数,如下示例:就是向容器当中存入bean的时候执行init
方法,然后销毁的时候执行destroy
方法。
@Configuration
public class Myconfig
@Bean ( initMethod = "init" , destroyMethod = "destroy" )
public User user01 ( )
User user = new User ( ) ;
return user;
public class User
private Integer id;
private String name;
private String phone;
public void init ( )
System . out. println ( "User初始化了" ) ;
public void destroy ( )
System . out. println ( "User销毁了" ) ;
destroy
方法在项目停止运行的时候是不会执行的,必须是项目仍然正常运行,从容器当中移除该对象,这时候是会执行destroy
方法的。
public class DemoUtil
@Autowired
private ApplicationContext applicationContext;
public void addBean ( String beanName, Class < ? > beanClass)
BeanDefinitionRegistry beanDefinitionRegistry = ( BeanDefinitionRegistry ) applicationContext. getAutowireCapableBeanFactory ( ) ;
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder . genericBeanDefinition ( beanClass) ;
BeanDefinition beanDefinition = beanDefinitionBuilder. getBeanDefinition ( ) ;
if ( ! beanDefinitionRegistry. containsBeanDefinition ( beanName) )
beanDefinitionRegistry. registerBeanDefinition ( beanName, beanDefinition) ;
public void removeBean ( String beanName)
BeanDefinitionRegistry beanDefinitionRegistry = ( BeanDefinitionRegistry ) applicationContext. getAutowireCapableBeanFactory ( ) ;
beanDefinitionRegistry. removeBeanDefinition ( beanName) ;
默认使用@Bean
配置的bean
,如果存在shutdown
方法,则在bean销毁时会自动执行该方法,如果你不想执行该方法,则添加@Bean(destroyMethod="")
来防止出发销毁方法
(5)Bean 增强
@Bean注释不提供Profile, Scope, Lazy, DependsOn, Primary, Order功能,意思是,如果要在bean上配置Profile, Scope, Lazy, DependsOn, Primary, Order这些的时候,不再是用属性了,而是在该bean上使用它们对应的注解。
@Bean
@Profile ( "dev" )
@Scope ( "prototype" )
@Order ( - 100 )
public MyBean myBean ( )
return obj;
@Profile: 指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境下都能注册这个组件@Scope: 他用来配置Bean实例的作用域对象。@Scope 具有以下几种作用域:
singleton
:单实例的(单例)(默认)----全局有且仅有一个实例prototype
:多实例的(多例)---- 每次获取Bean的时候会有一个新的实例reqeust
:同一次请求----request:每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效session
:同一个会话级别---- session:每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效 @Lazy: 可以延迟加载bean对象,即在使用时才去初始化。一是可以减少Spring的IOC容器启动时的加载时间,二是可以解决bean的循环依赖问题。@DependsOn: 主要用于指定当前bean所依赖的beans。任何被指定依赖的bean都由Spring保证在当前bean之前创建。在少数情况下,bean不是通过属性或构造函数参数显式依赖于另一个bean,但却需要要求另一个bean优先完成初始化,则可以使用@DependsOn这个注解。@Primary: 假如容器当中有两个A对象,使用@Autowired根据类型注入就会异常,@Primary是一种在注入点级别解决歧义的机制,可以解决该问题!@Order: 主要用来控制配置类的加载顺序,设置的值越小越优先加载!
(转)java之Spring(IOC)注解装配Bean详解
在这里我们要详细说明一下利用Annotation-注解来装配Bean。
因为如果你学会了注解,你就再也不愿意去手动配置xml文件了,下面就看看Annotation的魅力所在吧。
先来看看之前的bean注解装配例子:
package com.eco.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.eco.dao.UserDao;
import com.eco.model.User;
@Service
public class Userservice {
//@Autowired
private UserDao userdao;
public void setUserdao(UserDao userdao) {
this.userdao = userdao;
}
public void useradd(User newuser) {
userdao.adduser(newuser);
}
}
package com.eco.daoimp;
import org.hibernate.Session;
import org.hibernate.Transaction;import org.springframework.stereotype.Repository;
import com.eco.hibernate.HibernateSessionFactory;
import com.eco.dao.UserDao;
import com.eco.model.User;
@Repository
public class Usertodo1 implements UserDao {
public void adduser(User user) {
Session session = HibernateSessionFactory.getSession();
Transaction transaction = session.beginTransaction();
session.save(user);
transaction.commit();
session.close();
System.out.println("todo1 create the user");
}
}
由于这里只是讲注解,为了让代码看得更加清晰,就省略了方法内部的注释。
1.组件注解
@controller 控制器(注入服务)
@service 服务(注入dao)
@repository dao(实现dao访问)
@component (泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。)
其实在Annotation设计之初,是定义了四个组件注解的,每个组件注解声明该组件的功能,但是由于某种原因,这些设计
思想并未真正实现,以至于上面的四个组件注解都是一样的,没有任何区别;
所以当你搞不清当前要注解的类到底是dao层,service层,还是controller层时,建议使用@component注解;
或者说所有组件类都用@component注解,不然,万一dao层类你用了@service注解,虽然代码能够正常运行,但是明眼
人一看就知道你不专业,连dao层和service层都搞不清。
2.Autowired注解
采用@Autowired注解的成员变量、setter方法、构造方法(对应依赖注入的接口注入、setter注入、构造器注入),会让
Spring去做一件事:去所有@component注解的类里面找和我类型相同的,并装配到bean中,它默认是byType的,所以
如果你为多个与之类型相同的类注解了@component,那么Spring就说:我找到了好多和你类型相同的,这下该怎么办啊。
然后华丽丽地报错了。
所以我们建议在使用组件注解时给它起个名字,方式为@component("eco"),如果不自定义的话,Spring默认为组件起个
名字,这个名字就是该组件类名首字母小写。
那么在@Autowired(name="eco"),这样显式地声明注入的组件名称为eco,就不会出错了,但是你别故意注入一个类型不
匹配的,那就没意思了。
3.Resource注解
@Resource是一个比@Autowired注解功能更强大的注解,并且更易于理解;
@Autowired(name="eco")[email protected] (name="eco"),这两种注解功能是一样的,都能实现往此处注入一个名为
eco的类(资源)。
如此一来,就可以实现几个注解来实现xml文件手动装配bean的的功能了。
组件使用@Component注解,需要注入依赖(资源)就使用@Resource注解。
来源:http://www.cnblogs.com/eco-just/p/7852230.html
以上是关于@Bean注解详解的主要内容,如果未能解决你的问题,请参考以下文章
SpringBoot - @Bean注解详解
Java开发Spring之IOC详解第二篇(注解开发JdbcTemplatem模板Junit整合)
spring 技术详解 教程
java注解@Resource机制怎么取到注入过的Bean
spring在IoC容器中装配Bean详解
java注解@Resource机制怎么取到注入过的Bean