Spring Bean管理

Spring工厂类介绍

  • UML类图


    Spring Bean管理_第1张图片
    图片.png
  • bean加载过程 https://www.cnblogs.com/xrq730/p/6285358.html
  • 传统工厂类实现(方法已过时,仅供参考)
    @Test
    /**
     * 传统方式工厂类BeanFactory
     */
    public void demo4(){
        BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
        UserService userService = (UserService) beanFactory.getBean("userService");
        userService.sayHello();
    }

Bean实例化的三种方式

  • 在实例化其中之一的过程中,applicationContext.xml所有配置的bean都会被实例化。

第一种:采用无参数的构造方法的方式

  • Bean1.java
package com.alan.ioc.demo2;

/**
 * Bean的实例化的三种方式:采用无参数的构造方法的方式
 */
public class Bean1 {

    //无参构造
    public Bean1() {
        System.out.println("Bean1被实例化了。。。");
    }
}
  • applicationContext.xml配置
    
    
  • Test.java
    @Test
    /**
     * 采用无参数的构造方法的方式
     */
    public void demo1(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        Bean1 bean1 = (Bean1) applicationContext.getBean("bean1");
    }

第二种:采用静态工厂方式创建实例

  • Bean2.java
package com.alan.ioc.demo2;

/**
 * Bean的实例化三种方式:静态工厂实例化方式
 */
public class Bean2 {


}

  • Bean2Factory
package com.alan.ioc.demo2;

/**
 * Bean2的静态工厂
 */
public class Bean2Factory {

    public static Bean2 createBean2(){
        System.out.println("Bean2Factory的方法已经执行了。。。。");
        return  new Bean2();
    }
}

  • applicationContext.xml配置
    
    
  • Test.java
    @Test
    /**
     * 采用静态工厂方式实例化
     */
    public void demo2(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        Bean2 bean2 = (Bean2) applicationContext.getBean("bean2");
    }

第三种:采用实例工厂方式创建实例

  • Bean2.java
package com.alan.ioc.demo2;


/**
 * Bean的实例化三种方式:实例工厂实例化
 */
public class Bean3 {
}

  • Bean3Factory
package com.alan.ioc.demo2;

/**
 * Bean3的实例工厂(与静态工厂的区别,没有static修饰符)
 */
public class Bean3Factory {

    public Bean3 createBean3(){

        System.out.println("Bean3Factory执行了。。。");
        return  new Bean3();
    }
}

  • applicationContext.xml配置
    
    
    
  • Test.java
    @Test
    /**
     * 采用实例工厂方式实例化
     */
    public void demo3(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        Bean3 bean3 = (Bean3) applicationContext.getBean("bean3");
    }

Bean的常用配置

  • id和name
    1、id属性在IOC容器中必须是唯一的
    2、如果Bean的名称中含有特殊字符(例如struts总的“/”),就要使用时name.
    3、其实id和name功能基本是一致的
  • class
    用于设置一个类的完全路径名称,主要作用是IOC容器生成类的实例

Bean的作用域(scope属性)

  • 默认情况下是单例模式
    
    
  • 多例模式配置(整合struts需要使用)
    
    
Spring Bean管理_第2张图片
图片.png

Bean的生命周期

Spring Bean管理_第3张图片
图片.png
  • xml配置
    
  • Man.java
package com.alan.ioc.demo3;

public class Man {


    //无参构造
    public Man() {
        System.out.println("Man被实例化了。。。");
    }

    public void setup(){
        System.out.println("Man被初始化了。。。");
    }

    public void teardown(){
        System.out.println("Man被销毁了。。。");
    }
}
  • Test.java
***

    @Test
    public void demo2(){
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        Man man = (Man) applicationContext.getBean("man");
        System.out.println(man);

        applicationContext.close();
    }

Spring容器中Bean的生命周期

Spring Bean管理_第4张图片
图片.png

1:Bean的建立(实例化):

容器寻找Bean的定义信息并将其实例化。(instantiate bean)

2:属性注入:

使用依赖注入,Spring按照Bean定义信息配置Bean所有属性

3:如果Bean实现BeanNameAware接口,则执行setBeanName():

如果Bean类有实现org.springframework.beans.BeanNameAware接口,工厂调用Bean的setBeanName()方法传递Bean的ID。 (获得bean的id(name))

4:如果Bean实现BeanFactoryAware接口,则执行setBeanFactory():

如果Bean类有实现org.springframework.beans.factory.BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身。

5:如果存在BeanPostProcessors(后处理Bean),则执行ProcessBeforeInitialization()

如果有org.springframework.beans.factory.config.BeanPostProcessors和Bean关联,那么其postProcessBeforeInitialization()方法将被将被调 用。

6:如果Bean实现InitializingBean接口,则执行afterPropertiesSet():

如果Bean类已实现org.springframework.beans.factory.InitializingBean接口,则执行他的afterProPertiesSet()方法

7:Bean定义文件中定义init-method:

可以在Bean定义文件中使用"init-method"属性设定方法名称例如:

如果有以上设置的话,则执行到这个阶段,就会执行initBean()方法

8:BeanPostProcessors的ProcessaAfterInitialization()

如果有任何的BeanPostProcessors实例与Bean实例关联,则执行BeanPostProcessors实例的ProcessaAfterInitialization()方法

9:执行Bean类中自己定义的方法

10:如果Bean实现 DisposableBean接口,则执行destroy

11:Bean定义文件中定义destroy-method:

可以在Bean定义文件中使用"destroy-method"属性设定方法名称例如:

如果有以上设置的话,则执行到这个阶段,就会执行destoryBean()方法

代码实现十一个步骤
  • Bean.java
package com.alan.ioc.demo3;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class Man implements BeanNameAware , ApplicationContextAware , InitializingBean, DisposableBean {


    private String name;

    //无参构造
    public Man() {
        System.out.println("第一步:Man被实例化了。。。");
    }

    public void setName(String name) {
        System.out.println("第二步:设置属性");
        this.name = name;
    }

    /**
     * 使Spring知道创建这个Bean的名称(id)
     * @param name (xml中ID的值)
     */
    @Override
    public void setBeanName(String name) {
        System.out.println("第三步:设置Bean的名称"+ name);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("第四步:了解工厂的信息");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("第六步:属性设置后执行");
    }


    public void setup(){
        System.out.println("第七步:Man被初始化了。。。");
    }

    public void run(){
        System.out.println("第九步:执行自身定义的业务方法");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("第十步:执行Spring的销毁方法");
    }

    public void teardown(){
        System.out.println("第十一步:Man被销毁了。。。");
    }

}
  • MyBeanPostProcessor.java
package com.alan.ioc.demo3;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**
 * Spring中所有的bean都会执行此类中的方法
 */
public class MyBeanPostProcessor implements BeanPostProcessor {


    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("第五步:初识化前方法");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("第八步:初始化后方法");
        return bean;
    }
}
  • applicationContext.xml
    
    
        
    
    

BeanPostProcessor的作用

实例化时对类进行一些增强操作

package com.alan.ioc.demo3;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * Spring中所有的bean都会执行此类中的方法
 */
public class MyBeanPostProcessor implements BeanPostProcessor {


    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("第五步:初识化前方法");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("第八步:初始化后方法");
        //只对UserDao进行处理
        if("userDao".equals(beanName)){
            //产生代理
            Object proxy = Proxy.newProxyInstance(bean.getClass().getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    if("save".equals(method.getName())){
                        System.out.println("权限校验==================");
                       return method.invoke(bean,args);
                    }
                    return method.invoke(bean,args);
                }
            });
            return proxy;
        }else {
            return bean;
        }

    }
}

Spring属性注入

第一种 构造方法属性注入(demo4)
  • 通过构造方法注入Bean的属性值或依赖的对象,它保证了Bean实例在实例化后就可以使用。
  • 构造器注入在元素里声明的属性
    
    
        
        
    
  • User.java
package com.alan.ioc.demo4;

public class User {

    private String name;
    private Integer age;

    //带参构造
    public User(String name,Integer age){
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
  • test.java
package com.alan.ioc.demo4;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringDemo4 {


    @Test
    public void demo1(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user = (User) applicationContext.getBean("user");
        System.out.println(user);
    }
}

第二种 set方法属性注入,经常使用(demo4)
  • 通过设置注入的属性 ref 传入对象
  • Person.java
package com.alan.ioc.demo4;

public class Person {

    private String name;
    private Integer age;
    private Cat cat;


    //getter和setter方法
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Cat getCat() {
        return cat;
    }

    public void setCat(Cat cat) {
        this.cat = cat;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", cat=" + cat +
                '}';
    }
}
  • Cat.java
package com.alan.ioc.demo4;

public class Cat {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Cat{" +
                "name='" + name + '\'' +
                '}';
    }
}
  • xml
    
        
        
        
    

    
        
    
  • test.java
    @Test
    public void demo2(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        Person person = (Person) applicationContext.getBean("person");
        System.out.println(person);
    }

第三种 p名称空间方法属性注入

  • xml
   
   
   

第四种 Spel方式属性注入

Spring Bean管理_第5张图片
图片.png
  • Product.java
package com.alan.ioc.demo4;

public class Product {

    private String name;
    private Double price;
    private Category category;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    public Category getCategory() {
        return category;
    }

    public void setCategory(Category category) {
        this.category = category;
    }

    @Override
    public String toString() {
        return "Product{" +
                "name='" + name + '\'' +
                ", price=" + price +
                ", category=" + category +
                '}';
    }
}
  • Category.java
package com.alan.ioc.demo4;

public class Category {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Category{" +
                "name='" + name + '\'' +
                '}';
    }
}
  • ProductInfo.java
package com.alan.ioc.demo4;

public class ProductInfo {

    public Double calculatePrice(){
        return Math.random() * 199 ;
    }
}
  • applicationContext.xml
    
    
        
    

    

    
        
        
        
    
  • Test.java
    @Test
    public void demo3(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        Product product = (Product) applicationContext.getBean("product");
        System.out.println(product);
    }

复杂类型属性注入(数组、集合等 demo5)

    
    
        
        
            
                aaa
                bbb
                ccc
            
        
        
        
            
                111
                222
                333
            
        
        
        
            
                ddd
                eee
                fff
            
        
        
        
            
                
                
                
            
        
        
        
            
                alan
                alan
            
        
    

使用注解进行Bean管理

Spring Bean管理_第6张图片
图片.png
  • xml
    
    

  • UserService.java
package com.alan.demo1;

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

/**
 * Spring的Bean管理的注解方式
 * 相当于在xml配置 
 */

//@Component("userService")
@Service("userService")
public class UserService {

    public String sayHello(String name){
        return "hello "+name;
    }
}
  • Test.java
package com.alan.demo1;


import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringDemo1 {


    @Test
    public void demo1(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService) applicationContext.getBean("userService");
        System.out.println(userService.sayHello("alan"));
    }
}

属性注入注解方式实现

Spring Bean管理_第7张图片
图片.png
package com.alan.demo1;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * Spring的Bean管理的注解方式
 * 相当于在xml配置 
 */

//@Component("userService")
@Service("userService")
public class UserService {

    @Value("米饭")
    private String something;

    @Autowired
    @Qualifier("userDao")
    //@Resource(name = "userDao") //相当于上面两行注解
    private UserDao userDao;

    public String sayHello(String name){
        return "hello "+name;
    }

    public void eat(){
        System.out.println("eat:"+ something);
    }

    public void  save(){
        System.out.println("UserService中保存用户。。。");
        userDao.save();
    }

}
Spring Bean管理_第8张图片
图片.png
package com.alan.demo2;


import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

@Component("bean1")
public class Bean1 {


    @PostConstruct
    public void init(){
        System.out.println("initBean...");
    }

    public void say(){
        System.out.println("say....");
    }

    @PreDestroy
    public void destory(){
        System.out.println("destoryBean...");
    }
}

  • 两种方式同时使用xml需要填写

你可能感兴趣的:(Spring Bean管理)