2-SpringBean管理

目录 G:\8-CodeCloud\spring
项目名称 spring_ioc
项目文件夹 com.imooc.ioc.demo2;com.imooc.ioc.demo3;com.imooc.ioc.demo4
项目名称 spring_ioc_annotation
项目文件夹 com.imooc.ioc.demo1;com.imooc.ioc.demo2;com.imooc.ioc.demo3;

1. SpringBean管理的方式:XML方式

1.1 Bean配置方式

  1. 采用无参数的构造方法的方式
  2. 采用静态工厂实例化的方式
  3. 实例工厂实例化的方式

applicationContext.xml配置如下:

    
    
    
    
    
    
    
    

但实际工作中基本都是无参数的构造方法方式,其余2种方式意义不大。

1.2 Bean配置详解

(1)id与name
    
    

区别在于name中可以有特殊字符。

(2)bean的作用域
2-SpringBean管理_第1张图片
Bean的作用域.png

实验如下:通过打印对象地址来区分是否是同一对象

    @Test
    public void  demo1(){
        //创建工厂
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        //通过工厂获得类的实例
        Person person1 = (Person) applicationContext.getBean("person");
        Person person2 = (Person) applicationContext.getBean("person");

        System.out.println(person1);
        System.out.println(person2);
    }

(3)bean的生命周期

具体配置如下:

        

注意:
执行顺序 构造函数—>init-method—>destroy-method
destroy-method仅单例生效,并且只有在applicationContext工厂关闭的时候才会调用,工作中意义不大


完整的生命周期:
applicationContext2.xml中配置MyBeanPostProcessor

    
        
    

    

Man定义Spring Bean生命周期的步骤

package com.imooc.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 String getName() {
        return name;
    }

    public void setName(String name) {

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

    public Man(){
        System.out.println("第一步:Man被实例化了");
    }

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

    }

    public void teardown(){
        System.out.println("第十一步:执行自己的销毁方法,Man被销毁了");
    }

    @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 run(){
        System.out.println("第九步:执行业务方法");
    }

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

MyBeanPostProcessor是Spring中重要的方法涉及后续的AOP,代码如下:

package com.imooc.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;

public class MyBeanPostProcessor implements BeanPostProcessor{

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

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

具体的生命周期如下:

  1. Spring调用类的构造函数实例化
  2. DI:通过类的set方法初始化属性
  3. setBeanName 设置bean的名称
  4. setApplicationContext 了解工厂的信息
  5. 调用 MyBeanPostProcessor.postProcessBeforeInitialization 初始化前方法
  6. afterPropertiesSet 属性设置后
  7. init-method(配置文件中配置),进行初始化
  8. 调用 MyBeanPostProcessor.postProcessAfterInitialization 初始化后方法
  9. 执行业务方法
  10. destroy执行Spring 销毁方法
  11. destroy-method(配置文件中配置)执行自己的销毁方法,对象被销毁了
(4)Bean的增强

新建UserDao.java

package com.imooc.ioc.demo3;

public class UserDaoImpl implements UserDao {

    @Override
    public void findAll() {
        System.out.println("查询用户。。。。");
    }

    @Override
    public void save() {
        System.out.println("保存用户。。。。");

    }

    @Override
    public void update() {
        System.out.println("修改用户。。。。");

    }

    @Override
    public void delete() {
        System.out.println("删除用户。。。。");

    }
}

改造MyBeanPostProcessor.java,对userDao的sava方法进行增强

package com.imooc.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;

public class MyBeanPostProcessor implements BeanPostProcessor{

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

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

        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;
        }

    }
}

(5)Bean的属性注入

构造函数属性注入:

    
    
        
        
    

set方法属性注入1

    
    
        
        
    

set方法属性注入2

    
    
        
        
        
    

    
        
    

此外还有p名称空间属性注入、SpEL属性注入、复杂类型属性注入,由于工作中不常用就不记录了

2. SpringBean管理的方式:注解方式

2.1 Bean的管理

(1)开启注解扫描:如果下面的包中有注解就交给spring进行管理
    
    
(2)用注解代替XML文件定义Bean
2-SpringBean管理_第2张图片
使用注解定义bean.png
(3)用注解进行属性注入

属性注入的根本目的是为了初始化属性,使用属性的方法完成相应的功能
@Autowired 按照类型注入,如果存在两个相同Bean类型相同,则按照名称注入
@Autowired + @Qualifier("userDao") 按照类型注入的同时指定名称
@Resource(name="userDao") //@Resource 相当于@Autowired + @Qualifier
代码UserService.java

package com.imooc.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管理的注解方式
* 传统方式需要在applicationContext.xml中配置
*
*/
//@Component("userService")
@Service("userService")  //这里的名称,实际等效于bean id
public class UserService {

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

    @Autowired                //按照类型注入,如果存在两个相同Bean类型相同,则按照名称注入
    @Qualifier("userDao")     //单单用Qualifier注解没有注入userDao
    @Resource(name="userDao")   //@Resource 相当于@Autowired + @Qualifier

    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("service 保存用户方法。。。");
        userDao.save();
    }
}

(4)其他注解

@PostConstruct 相当于XML中的init-method
@PreDestroy相当于XML中的destroy-method,仅单例支持
@Scope("prototype")相当于XML中的scope

XML文件中的配置方式:

   

@PostConstruct @PreDestroy的使用方式:

package com.imooc.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("bean1 init 初始化方法。。。");
    }

    public void say(){
        System.out.println("bean1 say方法执行。。。");
    }

    @PreDestroy
    public void destroy(){
        System.out.println("bean1 destroy销毁方法。。。");
    }
}

@Scope("prototype")的使用方式,此时没有@PreDestroy

package com.imooc.demo2;


import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

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

@Component("bean2")
@Scope("prototype")
public class Bean2 {

    @PostConstruct
    public void init(){
        System.out.println("bean2 init 初始化方法。。。");
    }

    public void say(){
        System.out.println("bean2 say方法执行。。。");
    }

    @PreDestroy
    public void destroy(){
        System.out.println("bean2 destroy销毁方法。。。");
    }

}

你可能感兴趣的:(2-SpringBean管理)