美文网首页
2-SpringBean管理

2-SpringBean管理

作者: ichigoxxc | 来源:发表于2018-12-10 22:52 被阅读0次
    目录 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配置如下:

        <!--demo2 Bean 的实例化的三种方式-->
        <!--第一种:无参构造器方式-->
        <bean id="bean1" class="com.imooc.ioc.demo2.Bean1" />
        <!--第二种:静态工厂的方式-->
        <bean id="bean2" class="com.imooc.ioc.demo2.Bean2Factory" factory-method="createBean2"/>
        <!--第三种:实例工厂的方式-->
        <bean id="bean3Factory" class="com.imooc.ioc.demo2.Bean3Factory"/>
        <bean id="bean3" factory-bean="bean3Factory" factory-method="createBean3"/>
    

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

    1.2 Bean配置详解

    (1)id与name
        <bean id="bean1" class="com.imooc.ioc.demo2.Bean1" />
        <bean name="bean1@" class="com.imooc.ioc.demo2.Bean1" />
    

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

    (2)bean的作用域
    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的生命周期

    具体配置如下:

        <bean id="man" class="com.imooc.ioc.demo3.Man" init-method="setup" destroy-method="teardown"/>    
    

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


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

        <bean id="man" class="com.imooc.ioc.demo3.Man" init-method="setup" destroy-method="teardown">
            <property name="name" value="徐晓成"/>
        </bean>
    
        <bean class="com.imooc.ioc.demo3.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的属性注入

    构造函数属性注入:

        <!--Bean构造方法的属性注入,通过构造方法,在Bean实例化的时候对属性赋值-->
        <bean id="user" class="com.imooc.ioc.demo4.User">
            <constructor-arg name="name" value="徐晓成"/>
            <constructor-arg name="age" value="29"/>
        </bean>
    

    set方法属性注入1

        <!--Bean的set方法的属性注入-->
        <bean id="person" class="com.imooc.ioc.demo4.Person">
            <property name="name" value="徐晓成"/>
            <property name="age" value="29"/>
        </bean>
    

    set方法属性注入2

        <!--Bean的set方法的属性注入-->
        <bean id="person" class="com.imooc.ioc.demo4.Person">
            <property name="name" value="徐晓成"/>
            <property name="age" value="29"/>
            <property name="cat" ref="cat"/>
        </bean>
    
        <bean id="cat" class="com.imooc.ioc.demo4.Cat">
            <property name="name" value="ketty"/>
        </bean>
    

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

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

    2.1 Bean的管理

    (1)开启注解扫描:如果下面的包中有注解就交给spring进行管理
        <!--开启注解扫描,告诉spring如果下面的包中有注解就交给spring进行管理-->
        <context:component-scan base-package="com.imooc"/>
    
    (2)用注解代替XML文件定义Bean
    使用注解定义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中配置<bean id="" class=""/>
    *
    */
    //@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文件中的配置方式:

    <bean id="man" class="com.imooc.ioc.demo3.Man" init-method="setup" destroy-method="teardown"/>   
    <bean id="role" class="spring.chapter2.maryGame.Role" scope="prototype"/>
    

    @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管理

          本文链接:https://www.haomeiwen.com/subject/egtjhqtx.html