Spring详解

2017/11/10 - Java

Bean的生命周期

  1. 调用BeanFactoryPostProcessor的postProcessBeanFactory方法
  2. 调用Bean的构造函数(或者工厂方法)实例化Bean.
  3. 对Bean的成员变量赋值.
  4. 如果Bean实现了BeanNameAware,调用Bean的setBeanName方法.
  5. 如果Bean实现了BeanFactoryAware,调用Bean的setBeanFactory方法.
  6. 如果Bean实现了ApplicationContextAware,调用Bean的setApplicationContext方法.
  7. 如果容器中配置了BeanPostProcessor,调用BeanPostProcessor的postProcessBeforeInitialization方法(如果有多个,调用每一个)
  8. 如果Bean实现了InitializingBean,调用Bean的afterPropertiesSet方法.
  9. 如果Bean配置了init-method方法,调用init-method配置的Bean方法.
  10. 如果容器中配置了BeanPostProcessor,调用BeanPostProcessor的postProcessAfterInitialization方法.(如果有多个,调用每一个)
  11. Bean处于可以使用的状态.
  12. Spring容器关闭.
  13. 如果Bean实现了DisposableBean,调用Bean的destroy方法.
  14. 如果Bean配置了destroy-method方法,调用destroy-method配置的Bean的方法.

Bean

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

/**
 * 测试生命周期的Bean
 */
public class StudentBean implements InitializingBean, DisposableBean, BeanNameAware, BeanFactoryAware {
    private String name;
    private int age;

    private String beanName;//实现了BeanNameAware接口,Spring可以将BeanName注入该属性中
    private BeanFactory beanFactory;//实现了BeanFactory接口,Spring可将BeanFactory注入该属性中

    public StudentBean(){
        System.out.println("【Bean构造方法】学生类的无参构造方法");
    }

    @Override
    public String toString() {
        return "StudentBean{" +
            "name='" + name + '\'' +
            ", age=" + age +
            ", beanName='" + beanName + '\'' +
            '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("【set注入】注入学生的name属性");
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        System.out.println("【set注入】注入学生的age属性");
        this.age = age;
    }

    /**
     * 自己编写的初始化方法
     */
    public void myInit(){
        System.out.println("【init-method】调用init-method属性配置的初始化方法");
    }

    /**
     * 自己编写的销毁方法
     */
    public void myDestroy(){
        System.out.println("【destroy-method】调用destroy-method属性配置的销毁方法");
    }

    /**
     * BeanFactoryAware接口的方法
     * @param beanFactory
     * @throws BeansException
     */
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
        System.out.println("【BeanFactoryAware接口】调用BeanFactoryAware的setBeanFactory方法得到beanFactory引用");
    }

    /**
     * BeanNameAware接口的方法
     * @param name
     */
    @Override
    public void setBeanName(String name) {
        this.beanName = name;
        System.out.println("【BeanNameAware接口】调用BeanNameAware的setBeanName方法得到Bean的名称");
    }

    /**
     * InitializingBean接口的方法
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("【InitializingBean接口】调用InitializingBean接口的afterPropertiesSet方法");
    }

    /**
     * DisposableBean接口的方法
     * @throws Exception
     */
    @Override
    public void destroy() throws Exception {
        System.out.println("【DisposableBean接口】调用DisposableBean接口的destroy方法");
    }
}

BeanPostProcessor接口

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

public class MyBeanPostProcessor implements BeanPostProcessor {

    public MyBeanPostProcessor(){
        System.out.println("【BeanPostProcessor接口】调用BeanPostProcessor的构造方法");
    }

    @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("【BeanPostProcessor接口】调用postProcessBeforeInitialization方法,这里可对"+beanName+"的属性进行更改。");
            return bean;
        }

    @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("【BeanPostProcessor接口】调用postProcessAfterInitialization方法,这里可对"+beanName+"的属性进行更改。");
            return bean;
        }
}

BeanFactoryPostProcessor接口

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    public MyBeanFactoryPostProcessor() {
        System.out.println("【BeanFactoryPostProcessor接口】调用BeanFactoryPostProcessor实现类构造方法");
    }

    /**
     * 重写BeanFactoryPostProcessor接口的postProcessBeanFactory方法,可通过该方法对beanFactory进行设置
     */
    @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
        throws BeansException {
            System.out.println("【BeanFactoryPostProcessor接口】调用BeanFactoryPostProcessor接口的postProcessBeanFactory方法");
            BeanDefinition beanDefinition = beanFactory.getBeanDefinition("studentBean");
            beanDefinition.getPropertyValues().addPropertyValue("age", "21");
        }
}

Spring配置文件beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">

    <!--配置Bean的后置处理器-->
    <bean id="beanPostProcessor" class="com.xxx.cyclelife.MyBeanPostProcessor">
    </bean>

    <!--配置BeanFactory的后置处理器-->
    <bean id="beanFactoryPostProcessor" class="com.xxx.cyclelife.MyBeanFactoryPostProcessor">
    </bean>

    <bean id="studentBean" class="com.xxx.cyclelife.StudentBean" init-method="myInit"
    destroy-method="myDestroy" scope="singleton">
        <property name="name" value="xxx"></property>
        <property name="age" value="21"></property>
    </bean>

</beans>

常用注解

@Autowire和@Resource

共同点:

  • 均可标注在字段或属性的setter方法上。
  • 都可以通过@Qualifier显式指定 autowired by qualifier name。

区别:

  • @Autowired是spring的注解,使用AutowiredAnnotationBeanPostProcessor处理依赖注入。
  • @Resource来自于JSR-250位于java.annotation包,使用CommonAnnotationBeanPostProcessor处理依赖注入。
  • @Autowired默认 autowired by type,如果失败,则退化为autowired by field name;
  • @Resource默认autowired by field name,如果失败,则退化为autowired by type。可以使用@Autowired + @Qualifier实现@Resource的效果。
  • @Autowired有个required属性,配置为false时如果没有找到对应的bean是不会抛异常的。@Resource没有该配置,找不到会抛异常。

@Component和@Service、@Repository、@Controller

使用@Component注解标识类会生成响应的bean,默认的名称(id)是小写开头的非限定类名。也可以指定名称:@Component(“hello”),不推荐使用。

@Controller对应控制层的Bean,@Service对应的是业务逻辑层Bean,@Repository对应数据访问层也就是持久层的Bean。和@Component是等效的,区别在于后三个有具体的业务含义,分别对应web架构的3个分层。推荐使用后三者代替@Component,在spring未来的版本中,@Controller,@Service,@Repository会携带更多语义。并且便于开发和维护。

@Qualifier

当容器中存在同样类型的多个bean时,用@Qualifier注解指定注入Bean的名称 。

@ComponentScan

自动扫描包名下所有声明为Bean的类

@Bean

注解在方法上,声明当前方法的返回值为一个Bean

@PostConstruct

在构造函数执行完后执行

@PreDestroy

在Bean销毁之前执行

AOP注解(Demo

  • @Aspect //声明为切面
  • @PointCut //切点,定义拦截规则
  • @After
  • @Before
  • @Around

@Conditional

这个注解会检查条件,只有这个条件满足的时候,才会enable某些配置

标注在类上,声明配置类,相当于把该类作为spring的xml配置文件中的来使用。

  • @ConditionalOnClass 当classpath里面有一个或几个指定的类的时候才激活一个配置
  • @ConditionalOnMissingBean 当一个bean没有创建的时候,创建一个bean
  • @ConditionalOnBean
  • @ConditionalOnExpression
  • @ConditionalOnMissingClass
  • @ConditionalOnNotWebApplication
  • @ConditionalOnResource
  • @ConditionalOnWebApplication

@EnableXXX

使用@Import注解来做了一个简单的configuration import

@EnableTransactionManagement 启用了声明式的事务管理

@EnableWebMvc 启用Spring MVC

@EnableScheduling 初始化一个定时器。

@EnableConfigurationProperties 自动把一个POJO映射到一个Spring Boot配置文件(默认的是application.properties)里面的属性列表

@EnableAspectJAutoProxy 开启Spring对AspectJ的支持

未完待续


如果文章对您有帮助,欢迎扫描下方二维码赞助(一分也是爱噢),谢谢

Search

    一分也是爱噢 一分也是爱

    目录