java spring bean_Java——Spring Bean管理

1.Spring工厂类的继承方式

c0c17830602cb9a390f0f79d2cd6fe34.png

从上面可以看出,创建工厂类,可以通过ClassPathXmlApplicationContext和FileSystemXmlApplicationContext这两种方式:

FileSystemXmlApplicationContext从磁盘加载配置文件,此时就需要使用绝对路径。

public voiddemo3(){//创建Spring的工厂类

ApplicationContext applicationContext = new FileSystemXmlApplicationContext("C:\\applicationContext.xml");//通过工厂获得类

UserService userService = (UserService) applicationContext.getBean("userService");

userService.sayHello();

}

在之前老的版本中,同时通过BeanFactory来创建工厂类,这种方式虽然已经被弃用,但是依然可以使用:

@Testpublic voiddemo4(){

BeanFactory beanFactory= new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));

UserService userService= (UserService) beanFactory.getBean("userService");

userService.sayHello();

}

2.Bean的实例化三种方式

(1)使用类构造器实例化

public classBean1 {publicBean1(){

System.out.println("Bean1被实例化...");

}

}@Testpublic voiddemo1(){

ApplicationContext applicationContext= new ClassPathXmlApplicationContext("applicationContext.xml");

Bean1 bean1= (Bean1) applicationContext.getBean("bean1");

}

(2)使用构造工厂实例化

public classBean2 {

}public classBean2Factory {public staticBean2 createBean2(){

System.out.println("Bean2Facyory方法已经执行");return newBean2();

}

}@Testpublic voiddemo2(){

ApplicationContext applicationContext= new ClassPathXmlApplicationContext("applicationContext.xml");

Bean2 bean2= (Bean2) applicationContext.getBean("bean2");

}

new ClassPathXmlApplicationContext("applicationContext.xml")会实例化applicationContext.xml配置文件中所有的构造类。

(3)使用实例工厂方法实例化

public classBean3 {

}public classBean3Factory {publicBean3 createBean3(){

System.out.println("Bean3Factory已经实例化");return newBean3();

}

}

@Testpublic voiddemo3() {

ApplicationContext applicationContext= new ClassPathXmlApplicationContext("applicationContext.xml");

Bean3 bean3= (Bean3) applicationContext.getBean("bean3");

}

一般默认情况,我们会采用无参数的构造方法的方式。如果类的构造特别复杂,我们会使用第二种或者第三种方式。

3.Bean的配置

(1)id和name

一般情况下,装配一个Bean时,通过指定一个id属性作为Bean的名称。

id属性在IOC容器中必须是唯一的。

如果Bean的名称中含有特殊字符,就需要使用name属性。

(2)class

class用于设置一个类的完全路径名称,主要作用是IOC容器生成类的实例。

(3)scope

用于控制bean的作用域

scope常用的选项:

ef18395c2df66d99e1f260daf8d362cd.png

request和session是针对web开发来说。

默认采用singleton模式:

public voiddemo1(){

ApplicationContext applicationContext= new ClassPathXmlApplicationContext("applicationContext.xml");

Person person1= (Person) applicationContext.getBean("person");

Person person2= (Person) applicationContext.getBean("person");

System.out.println(person1);//com.imooc.ioc.demo3.Person@544a2ea6

System.out.println(person2); //com.imooc.ioc.demo3.Person@544a2ea6

}

可以看到,每次创建的对象都指向一个实例。

public voiddemo1(){

ApplicationContext applicationContext= new ClassPathXmlApplicationContext("applicationContext.xml");

Person person1= (Person) applicationContext.getBean("person");

Person person2= (Person) applicationContext.getBean("person");

System.out.println(person1);//com.imooc.ioc.demo3.Person@544a2ea6

System.out.println(person2); //com.imooc.ioc.demo3.Person@2e3fc542

}

如果采用prototype模式,每次都会生成一个新的对象。

4.Bean的生命周期

Spring初始化bean或销毁bean时,有时需要做一些处理工作,

因此spring可以在创建和销毁bean的时候调用bean的两个生命周期方法。

在创建的时候可以使用init-method参数来指定创建方法。

在销毁的时候可以使用destory-method参数来指定销毁方法,同时必须scope="singleton"

public classMan {publicMan(){

System.out.println("Man被实例化");

}public voidsetup(){

System.out.println("Man被初始化了");

}public voidteardown(){

System.out.println("Man被销毁了");

}

}

public voiddemo2(){

ClassPathXmlApplicationContext applicationContext= new ClassPathXmlApplicationContext("applicationContext.xml");

Man man= (Man) applicationContext.getBean("man");

applicationContext.close();

}

打印结果:

Man被实例化

Man被初始化了

Man被销毁了

5.Bean的生命周期的完整过程

a6ce60ce3267c6e3d69efd95c64f7f57.png

(1)instantiate bean对象实例化

(2)populate properties封装属性

(3)如果Bean实现BeanNameAware执行setBeanName(获取当前类在spring中的配置名称,也就是id值)

(4)如果Bean实现BeanFactoryAware或者ApplicationContextAware,

设置工厂setBeanFactory或者上下文对象setApplicationContext。(了解工厂信息)

(5)如果存在类实现BeanPostProcessor(后处理Bean),执行postProcessBeforeInitialization

(6)如果Bean实现了InitializingBean执行afterPropertiesSet

(7)调用指定初始化方法init

(8)如果存在类实现BeanPostProcessor(处理Bean),执行postProcessAfterInitialization

(9)执行业务处理

(10)如果Bean实现了DisposableBean执行destroy

(11)调用指定销毁方法customerDestroy,这个是用户自定义的销毁方法

packagecom.imooc.ioc.demo3;importorg.springframework.beans.BeansException;importorg.springframework.beans.factory.BeanNameAware;importorg.springframework.beans.factory.DisposableBean;importorg.springframework.beans.factory.InitializingBean;importorg.springframework.context.ApplicationContext;importorg.springframework.context.ApplicationContextAware;public class Man implementsBeanNameAware, ApplicationContextAware, InitializingBean, DisposableBean {privateString name;public voidsetName(String name) {

System.out.println("第二步:设置属性");this.name =name;

}publicMan(){

System.out.println("第一步:初始化...");

}public voidsetup(){

System.out.println("第七步:Man被初始化了");

}public voidteardown(){

System.out.println("第十一步:Man被销毁了");

}public voidsetBeanName(String s) {

System.out.println("第三步:设置Bean的名称" +s);

}public void setApplicationContext(ApplicationContext applicationContext) throwsBeansException {

System.out.println("第四步:了解工厂信息");

}public void afterPropertiesSet() throwsException {

System.out.println("第六步:属性设置后");

}public voidrun(){

System.out.println("第九步:执行业务方法");

}public void destroy() throwsException {

System.out.println("第十步:执行Spring的销毁方法");

}

}packagecom.imooc.ioc.demo3;importorg.springframework.beans.BeansException;importorg.springframework.beans.factory.config.BeanPostProcessor;public class MyBeanPostProcessor implementsBeanPostProcessor {public Object postProcessBeforeInitialization(Object bean, String beanName) throwsBeansException {

System.out.println("第五步:初始化前方法...");returnbean;

}public Object postProcessAfterInitialization(Object bean, String beanName) throwsBeansException {

System.out.println("第八步:初始化后方法...");returnbean;

}

}public voiddemo2(){

ClassPathXmlApplicationContext applicationContext= new ClassPathXmlApplicationContext("applicationContext.xml");

Man man= (Man) applicationContext.getBean("man");

man.run();

applicationContext.close();

}

6.BeanPostProcessor——增强类方法

实现接口类:

public interfaceUserDao {public voidfindAll();public voidsave();public voidupdate();public voiddelete();

}

创建实现类:

public class UserDaoImpl implementsUserDao {public voidfindAll() {

System.out.println("查询用户");

}public voidsave() {

System.out.println("保存用户");

}public voidupdate() {

System.out.println("修改用户");

}public voiddelete() {

System.out.println("删除用户");

}

}

调用类方法

public voiddemo3(){

ApplicationContext applicationContext= new ClassPathXmlApplicationContext("applicationContext.xml");

UserDao userDao= (UserDao)applicationContext.getBean("userDao");

userDao.findAll();

userDao.save();

userDao.update();

userDao.delete();

}

方法增强:

如果我们想增强一个方法,当然我们单独再定义一个方法,再此之前调用,

但是如果调用的次数非常多,这样就非常麻烦,这样我们可以使用BeanPostProcessor

public Object postProcessAfterInitialization(final Object bean, String beanName) throwsBeansException {

System.out.println("第八步:初始化后方法...");if ("userDao".equals(beanName)){ //匹配到对应的类

Object proxy = Proxy.newProxyInstance(bean.getClass().getClassLoader(), bean.getClass().getInterfaces(), newInvocationHandler() {public Object invoke(Object proxy, Method method, Object[] args) throwsThrowable {if ("save".equals(method.getName())){ //对于sava方法添加一点配置

System.out.println("权限校验");returnmethod.invoke(bean,args);

}returnmethod.invoke(bean,args);

}

});returnproxy;

}returnbean;

}

7.属性注入方法及构造方法的属性注入

(1)构造方法注入

packagecom.imooc.ioc.demo4;public classUser {privateString name;privateInteger age;publicUser() {}publicUser(String name, Integer age) {this.name =name;this.age =age;

}

@OverridepublicString toString() {return "User{" +

"name='" + name + '\'' +

", age=" + age +

'}';

}

}

@Testpublic voiddemo1(){

ApplicationContext applicationContext= new ClassPathXmlApplicationContext("applicationContext.xml");

User user= (User) applicationContext.getBean("user");

System.out.println(user);

}

(2)Set方法注入

使用set方法注入,在Spring配置文件中,通过设置注入的属性。

public classPerson {privateString name;privateInteger age;publicString getName() {returnname;

}public voidsetName(String name) {this.name =name;

}publicInteger getAge() {returnage;

}public voidsetAge(Integer age) {this.age =age;

}

@OverridepublicString toString() {return "Person{" +

"name='" + name + '\'' +

", age=" + age +

'}';

}

public voiddemo1(){

ApplicationContext applicationContext= new ClassPathXmlApplicationContext("applicationContext.xml");

Person person= (Person) applicationContext.getBean("person");

System.out.println(person);

}

如果我现在将注入一个关联类,该如何处理了?

比如我现在给人添加一只宠物吗?

public classCat {privateString name;

}public classPerson {privateString name;privateInteger age;privateCat cat;

@OverridepublicString toString() {return "Person{" +

"name='" + name + '\'' +

", age=" + age +

", cat=" + cat.getName() +

'}';

}

}

在属性注入的时候,使用关联注入即可。

(3)P名称空间的属性注入

使用P命名空间。

为了简化XML文件配置,Spring从2.5开始引入一个新的P名称空间。

如果是一般属性,这样书写:

p:="xxx" 引入常量值

p:-ref="xxx"引入其他Bean对象

上面实例就可以这样些:

(4)SpEL属性注入

SpEL:spring expression language,spring表达式语言,对依赖注入进行简化的语法:#{表达式}

SpEL表达式语言:

语法:#{}

#{ ‘hello’ }:使用字符串

#{beanId}:使用另一个bean

#{beanId.content.toUpperCase()}:使用指定名属性,并使用方法

#{T(java.lang.Math).PI}:使用静态字段或方法

创建关联类:

public classCategory {privateString name;publicString getName() {returnname;

}public voidsetName(String name) {this.name =name;

}

@OverridepublicString toString() {returnname;

}

}

创建实例类:

public classProductInfo {publicDouble discountPrice(){return 188.8;

}

}public classProduct {privateString name;privateDouble price;privateCategory category;publicString getName() {returnname;

}public voidsetName(String name) {this.name =name;

}publicDouble getPrice() {returnprice;

}public voidsetPrice(Double price) {this.price =price;

}publicCategory getCategory() {returncategory;

}public voidsetCategory(Category category) {this.category =category;

}

@OverridepublicString toString() {return "Product{" +

"name='" + name + '\'' +

", price=" + price +

", category=" + category +

'}';

}

}

Bean管理:

引用工厂类的方法

调用:

public voiddemo1(){

ApplicationContext applicationContext= new ClassPathXmlApplicationContext("applicationContext.xml");

Product product= (Product) applicationContext.getBean("product");

System.out.println(product);

}

(5)负责类型的属性注入

数组类型的属性注入

List集合类型的属性注入

Set集合类型的属性注入

Map集合类型的属性注入

Properties类型的属性注入

创建实例类:

public classCollectionBean {private String[] arrs; //数组类型

private List list; //List集合类型

private Set set; //Set集合类型

private Map map; //Map集合类型

private Properties properties; //属性类型

publicString[] getArrs() {returnarrs;

}public voidsetArrs(String[] arrs) {this.arrs =arrs;

}public ListgetList() {returnlist;

}public void setList(Listlist) {this.list =list;

}public SetgetSet() {returnset;

}public void setSet(Setset) {this.set =set;

}public MapgetMap() {returnmap;

}public void setMap(Mapmap) {this.map =map;

}publicProperties getProperties() {returnproperties;

}public voidsetProperties(Properties properties) {this.properties =properties;

}

@OverridepublicString toString() {return "CollectionBean{" +

"arrs=" + Arrays.toString(arrs) +

", list=" + list +

", set=" + set +

", map=" + map +

", properties=" + properties +

'}';

}

}

Bean管理:

a

b

c

11

22

33

10

20

30

ming

123456

调用:

public void demo1(){

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");

CollectionBean collectionBean = (CollectionBean) applicationContext.getBean("collectionBean");

System.out.println(collectionBean);

//CollectionBean{arrs=[a, b, c], list=[11, 22, 33], set=[10, 20, 30], map={a=1, b=2, c=3}, properties={password=123456, username=ming}}

}

8.Bean管理的注解方式

(1)简单使用

Spring2.5引入使用注解去定义Bean。

@Component 描述Spring框架中Bean,这样就无需在XML文件中进行配置

除了@Component外,Spring提供了3个基本功能和@Component等效的注解:

@Repository 用于对DAO实现类进行标注

@Service 用于对Service实现类进行标注

@Controller 用于对Controller实现类进行标注

比如:

importorg.springframework.stereotype.Component;

@Component("userService")public classUserService {publicString sayHello(String name){return "Hello" +name;

}

}public voiddemo1(){

ApplicationContext applicationContext= new ClassPathXmlApplicationContext("applicationContext.xml");

UserService userService= (UserService) applicationContext.getBean("userService");

System.out.println(userService.sayHello("ming"));

}

注解会帮我们完成XML的Bean配置。

(2)属性注入

使用@Autowored进行自动注入

@Autowired默认按照类型进行注入

如果存在两个相同Bean,则按照名称注入

@Autowired注入时可以针对成员变量或者set方法

通过@Autowired的required属性,设置一定要找到匹配的Bean。

使用@Qualifier指定注入Bean的名称

@Component("userService")public classUserService {

@Value("鱼") //常规属性注入

privateString food;

@Autowired//对象注入

privateUserDao userDao;publicString sayHello(String name){return "Hello" +name;

}public voideat(){

System.out.println("eat: " +food);

}public voidsave(){

System.out.println("Service中保存用户");

userDao.save();//将对象注入之后,才能调用其中的方法

}

}

使用@Qualifier按照名称才能完成注入

@Autowired //对象注入

@Qualifier("userDao")private UserDao userDao;

@Resource相当于@Autowired+@Qualifier的功能。

类中如果有setter方法,那么注解需要加到setter方法上边。

(3)生命周期的注解

Spring初始化bean或销毁bean时,有时候需要一些处理工作,

因此Spring可以在创建和拆卸bean的时候,调用bean的两个生命周期方法。

那么如何使用注解的方式来完成了?

init-method初始化的时候,可以用@PostConstruct来代替。

destory-method销毁对象时,可以使用@PreDestroy

@Component("bean1")public classBean1 {

@PostConstructpublic voidinit(){

System.out.println("initBean...");

}public voidsay(){

System.out.println("say...");

}

@PreDestroypublic voiddestory(){

System.out.println("destroyBean...");

}

}public voiddemo2() {

ClassPathXmlApplicationContext classPathXmlApplicationContext= new ClassPathXmlApplicationContext("applicationContext.xml");

Bean1 bean1= (Bean1) classPathXmlApplicationContext.getBean("bean1");

bean1.say();

classPathXmlApplicationContext.close();

}

(4)注入范围的注解

使用注解配置的Bean和配置的一样,默认作用范围都是singleton。

使用@Scope注解用于指定Bean的作用范围。

@Component("bean2")public classBean2 {

}public voiddemo2() {

ClassPathXmlApplicationContext classPathXmlApplicationContext= new ClassPathXmlApplicationContext("applicationContext.xml");

Bean2 bean1= (Bean2) classPathXmlApplicationContext.getBean("bean2");

Bean2 bean2= (Bean2) classPathXmlApplicationContext.getBean("bean2");

System.out.println(bean1);//com.imooc.demo2.Bean2@79ca92b9

System.out.println(bean2); //com.imooc.demo2.Bean2@79ca92b9

}

如果指定作用范围:

@Component("bean2")

@Scope("prototype")public classBean2 {

}

结果将完全不同:

public voiddemo2() {

ClassPathXmlApplicationContext classPathXmlApplicationContext= new ClassPathXmlApplicationContext("applicationContext.xml");

Bean2 bean1= (Bean2) classPathXmlApplicationContext.getBean("bean2");

Bean2 bean2= (Bean2) classPathXmlApplicationContext.getBean("bean2");

System.out.println(bean1);//com.imooc.demo2.Bean2@1198b989

System.out.println(bean2); //com.imooc.demo2.Bean2@7ff95560

}

9.传统XML配置和注解整合开发

XML方式的优势:

结构清晰,易于阅读

注解方式的优势:

开发便捷,属性注入方便

XML与注解和整合开发

1.引入context命名空间

2.在配置文件中添加context:annotation-config标签

(1)传统方式

public classCategoryDao {public voidsave(){

System.out.println("CategoryDao中sava方法执行了");

}

}public classProductDao {public voidsave(){

System.out.println("ProductDao中sava方法执行了");

}

}public classProductService {privateCategoryDao categoryDao;privateProductDao productDao;publicCategoryDao getCategoryDao() {returncategoryDao;

}public voidsetCategoryDao(CategoryDao categoryDao) {this.categoryDao =categoryDao;

}publicProductDao getProductDao() {returnproductDao;

}public voidsetProductDao(ProductDao productDao) {this.productDao =productDao;

}public voidsave(){

System.out.println("ProductService的save方法");

categoryDao.save();

productDao.save();

}

}

public voiddemo1(){

ApplicationContext applicationContext= new ClassPathXmlApplicationContext("applicationContext.xml");

ProductService productService= (ProductService) applicationContext.getBean("productService");

productService.save();

}

(2)混合开发

如果此时属性注入想使用注解方式,那么可以这样:

public classProductService {

@Resource(name="categoryDao") //属性注入

privateCategoryDao categoryDao;

@Resource(name="productDao")privateProductDao productDao;public voidsave(){

System.out.println("ProductService的save方法");

categoryDao.save();

productDao.save();

}

}public voiddemo1(){

ApplicationContext applicationContext= new ClassPathXmlApplicationContext("applicationContext.xml");

ProductService productService= (ProductService) applicationContext.getBean("productService");

productService.save();

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值