Spring_Spring与IoC_Bean的装配

Posted hoje

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring_Spring与IoC_Bean的装配相关的知识,希望对你有一定的参考价值。

一、Bean的装配

     bean的装配,即Bean对象的创建,容器根据代码要求来创建Bean对象后再传递给代码的过程,称为Bean的装配。

 二、默认装配方式

    代码通过getBean()方式从容器获取指定的Bean示例,容器首先会调用Bean类的无参构造器,创建空值的示例对象。

三、工厂方法设计模式(为了解耦合)

1 public class ServiceFactory {
2    public ISomeService getISomeService(){
3     return new SomeServiceImpl();   
4    }
5 }
@Test
    public void test01() {
        ISomeService service=new ServiceFactory().getISomeService();
        service.doSome();
    }

静态工厂

public class ServiceFactory {
   public static ISomeService getISomeService(){
    return new SomeServiceImpl();   
   }
}
@Test
    public void test01() {
        ISomeService service=ServiceFactory.getISomeService();
        service.doSome();
    }

四、动态工厂Bean

public class ServiceFactory {
   public ISomeService getSomeService(){
    return new SomeServiceImpl();   
   }
}
 <!--注册动态工厂 -->
   <bean id="factory" class="com.jmu.ba02.ServiceFactory"></bean>
@SuppressWarnings("resource")
    @Test
    public void test02() {
        //创建容器对象
        String resource = "com/jmu/ba02/applicationContext.xml";
        ApplicationContext ac=new ClassPathXmlApplicationContext(resource);
        ServiceFactory factory=(ServiceFactory) ac.getBean("factory");
        ISomeService service = factory.getSomeService();
        service.doSome();
    }

但以上方法不好。修改如下(测试类看不到工厂,也看不到接口的实现类)

<!--注册service:动态工厂Bean-->
    <bean id="myService" factory-bean="factory" factory-method="getSomeService"></bean>
@SuppressWarnings("resource")
    @Test
    public void test02() {
        //创建容器对象
        String resource = "com/jmu/ba02/applicationContext.xml";
        ApplicationContext ac=new ClassPathXmlApplicationContext(resource);
        ISomeService service = (ISomeService) ac.getBean("myService");
        service.doSome();
    }

五、静态工厂Bean

public class ServiceFactory {
   public static ISomeService getSomeService(){
    return new SomeServiceImpl();   
   }
}
 <!--注册动态工厂 :静态工厂Bean-->
    <bean id="myService" class="com.jmu.ba03.ServiceFactory" factory-method="getSomeService"></bean>
@Test
    @SuppressWarnings("resource")
    public void test02() {
        //创建容器对象
        String resource = "com/jmu/ba03/applicationContext.xml";
        ApplicationContext ac=new ClassPathXmlApplicationContext(resource);
        ISomeService service = (ISomeService) ac.getBean("myService");
        service.doSome();
    }

 六、Bean的装配

1、Singleton单例模式:

 

 

2、原型模式prototype:

 

3、request:对于每次HTTP请求,都会产生一个不同的Bean实例

4、Session:对于每次不同的HTTP session,都会产生一个不同的Bean实例

七、Bean后处理器

  bean后处理器是一种特殊的Bean,容器中所有的Bean在初始化时,均会自动执行该类的两个方法,由于该Bean是由其他Bean自动调用执行,不是程序员手动创建,所有Bean无需id属性。

  需要做的是,在Bean后处理器类方法中,只要对Bean类与Bean类中的方法进行判断,就可以实现对指定的Bean的指定方法进行功能扩展和增强。方法返回的Bean对象,即是增强过的对象。

  代码中需要自定义Bean后处理下类,该类就是实现了接口BeanPostProcessor的类。该接口包含2个方法,分别在目标Bean初始化完毕之前和之后执行,它们的返回值为:功能被扩展或增强后的Bean对象。

 1 import org.springframework.beans.BeansException;
 2 import org.springframework.beans.factory.config.BeanPostProcessor;
 3 
 4 public class MyBeanPostProcessor implements BeanPostProcessor {
 5    //bean:表示当前正在进行初始化的Bean对象
 6    //beanName:表示当前正在进行初始化的Bean对象的id
 7     @Override
 8     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
 9         // TODO Auto-generated method stub
10         System.out.println("执行before");
11         return bean;
12     }
13     @Override
14     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
15         // TODO Auto-generated method stub
16         System.out.println("执行after");
17         return bean;
18     }
19 
20 
21 }
MyBeanPostProcessor
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xsi:schemaLocation="
 5         http://www.springframework.org/schema/beans 
 6         http://www.springframework.org/schema/beans/spring-beans.xsd">
 7 
 8     <bean id="myService" class="com.jmu.ba05.SomeServiceImpl"></bean>
 9     <!--注册bean后处理器 -->
10     <bean class="com.jmu.ba05.MyBeanPostProcessor"></bean>
11 </beans>
applicationContext.xml

输出:

1 执行doSome()方法
2 log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment).
3 log4j:WARN Please initialize the log4j system properly.
4 执行before
5 执行after
6 执行doSome()方法
输出

八、Bean后处理器的应用

要求:增强service的doSome()

1 public interface ISomeService {
2    String doSome();
3    String doOther();
4 }
ISomeService
 1 public class SomeServiceImpl implements ISomeService {
 2 
 3     @Override
 4     public String doSome() {
 5         // TODO Auto-generated method stub
 6       System.out.println("执行doSome()方法");
 7       return "abcd";
 8     }
 9 
10     @Override
11     public String doOther() {
12         // TODO Auto-generated method stub
13           System.out.println("执行doOther()方法");
14         return "fight";
15     }
16 
17 }
SomeServiceImpl
 1 import java.lang.reflect.InvocationHandler;
 2 import java.lang.reflect.Method;
 3 import java.lang.reflect.Proxy;
 4 
 5 import org.springframework.beans.BeansException;
 6 import org.springframework.beans.factory.config.BeanPostProcessor;
 7 
 8 public class MyBeanPostProcessor implements BeanPostProcessor {
 9    //bean:表示当前正在进行初始化的Bean对象
10    //beanName:表示当前正在进行初始化的Bean对象的id
11     @Override
12     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
13         // TODO Auto-generated method stub
14         System.out.println("执行before");
15         return bean;
16     }
17     @Override
18     public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
19         // TODO Auto-generated method stub
20         System.out.println("执行after");
21         if ("myService".equals(beanName)) {
22             Object obj = Proxy.newProxyInstance(bean.getClass().getClassLoader(), bean.getClass().getInterfaces(),
23                     new InvocationHandler() {
24 
25                         @Override
26                         public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
27                             Object invoke = method.invoke(bean, args);
28                             if ("doSome".equals(method.getName())) {
29                                 // TODO Auto-generated method stub
30                                 return ((String) invoke).toUpperCase();
31                             }
32                             return  invoke;
33                         }
34                     });
35             //类加载器:bean.getClass().getClassLoader()
36             //final:内部类使用外部类的成员变量,外部成员变量需要为fianl
37             return obj;
38         }
39         return bean;
40     }
41 
42 
43 }
MyBeanPostProcessor
1     <bean id="myService" class="com.jmu.ba05.SomeServiceImpl"></bean>
2     <bean id="myService2" class="com.jmu.ba05.SomeServiceImpl"></bean>
3     <!--注册bean后处理器 -->
4     <bean class="com.jmu.ba05.MyBeanPostProcessor"></bean>
applicationContext.xml
 1 @SuppressWarnings("resource")
 2     @Test
 3     public void test02() {
 4         //创建容器对象
 5         String resource = "com/jmu/ba05/applicationContext.xml";
 6         ApplicationContext ac=new ClassPathXmlApplicationContext(resource);
 7         ISomeService service=(ISomeService) ac.getBean("myService");
 8         System.out.println(service.doSome());
 9         System.out.println(service.doOther());
10         
11         System.out.println("--------------------");
12         
13         ISomeService service2=(ISomeService) ac.getBean("myService2");
14         System.out.println(service2.doSome());
15         System.out.println(service2.doOther());
16     }
MyTest

输出:

执行doSome()方法
log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment).
log4j:WARN Please initialize the log4j system properly.
执行before
执行after
执行before
执行after
执行doSome()方法
ABCD
执行doOther()方法
fight
--------------------
执行doSome()方法
abcd
执行doOther()方法
fight
output

九、定制Bean的生命周期始末

十、id与name属性

name可以包含各种字符,id的命名必须以字母开头。

以上是关于Spring_Spring与IoC_Bean的装配的主要内容,如果未能解决你的问题,请参考以下文章

Spring_Spring的核心_总结

Spring Boot 自动装配定义与自定义starter原理,及如何实现自定义装配

Spring Boot 自动装配定义与自定义starter原理,及如何实现自定义装配

装配精度与装配尺寸

XML配置里的Bean自动装配与Bean之间的关系

Spring学习Bean自动装配与注解开发