Bean的生命周期

本文深入探讨Spring框架下Bean的生命周期管理,从Bean的实例化、初始化到销毁的全过程,包括如何利用BeanPostProcessor等接口定制Bean的生命周期行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

这里要先了解Bean的后置处理器(BeanProstProcessor):

我们可以理解为大多数情况下在创建了对象之后,可以进行对对象的其他操作,再转化成Bean

@Component
public class FactoryBeanProstProcessor implements BeanPostProcessor {
​
    
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return null;
    }
​
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return null;
    }
​
​
}

 

使用后置处理找到对应类中属性的注解

就相当于对这个对象进行处理(赋值等等...)

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface LuoLuo  {
​
    String value();
}
​
@ComponentScan("com.test")//扫描路径
public class Config {
​
}
​
@Component
public class FactoryBeanProstProcessor implements BeanPostProcessor {
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        Class<?> clazz = bean.getClass();
        for (Field field : clazz.getDeclaredFields()) {
            if (field.isAnnotationPresent(LuoLuo.class)){
                LuoLuo fieldAnnotation = field.getAnnotation(LuoLuo.class);//得到这个属性上的注解
                String s = fieldAnnotation.value();//讲注解赋值给s
                System.out.println(s);
            }
        }
        return null;
    }
}
public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);//通过Config配置得到对象
        UserService userService = (UserService) context.getBean("userService");
        System.out.println(userService);
​
    }
​
最后输出
xiaoluoxxx
​

实例化

@ComponentScan("com.user")
public class Config {
}
@Component
public class UserService {
    public UserService() {
        System.out.println("我是无参构造");
    }
}
​
 public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
        UserService userService = context.getBean("userService", UserService.class);
        System.out.println(userService);
    }
​
我是无参构造
com.user.UserService@42607a4f

实例化前

@Component
public class LLBeanPostProcess implements InstantiationAwareBeanPostProcessor {
​
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if (beanName.equals("userService")){
            System.out.println("实例化前");
        }
        return null;
    }
    
    实例化前
    我是无参构造
com.user.UserService@6fb0d3ed

 

如果实例化前给他直接返回一个对象,那么就不会再进行实例化

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
    if (beanName.equals("userService")){
        System.out.println("实例化前");
    }
    return new UserService();
}

实例化和推断构造方法

@Component
public class UserService {
​
    private User user;
​
    public UserService(User user) {
        this.user=user;
        System.out.println("一个有参构造");
    }
}
​
只有一个有参构造就直接调用
一个有参构造
​
​
@Component
public class UserService {
​
    private User user;
​
    public UserService(User user) {
        this.user=user;
        System.out.println("一个有参构造");
    }
    
​
    @Autowired//必须的必要的
    public UserService(User user,User user1) {
        this.user=user;
        System.out.println("二个有参构造");
    }
    
    二个有参构造
        
   有两个有参就会报错,但是只要给他一个注解,他就会自动判断有注解的哪一个
       
       
        @Autowired(required = false)
    public UserService(User user) {
        this.user=user;
        System.out.println("一个有参构造");
    }
​
​
    @Autowired(required = false)
    public UserService(User user,User user1) {
        this.user=user;
        System.out.println("二个有参构造");
    }
​
    按照自己的逻辑会选一个构造方法会先选参数多的
    如果一样多就会按顺序选择.
       

实例化后

 

@Component
public class LLBeanPostProcess implements InstantiationAwareBeanPostProcessor {
​
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
​
        return null;
    }
​
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if (beanName.equals("userService")){
            System.out.println("我是后置");
        }
        return true;
    }
}
​
@Component
public class UserService {
​
    private User user;
​
    public UserService() {
        System.out.println("我是无参构造方法");
    }
​
    @Autowired
    public void setUser(User user) {
        System.out.println("set方法注入");
        this.user = user;
    }
}
​
我是无参构造方法
我是后置
set方法注
    
    我们可以在实例化后操作这个对象的属性
    
    

初始化

 

@Component
public class UserService implements InitializingBean {
​
    private User user;
​
    public UserService() {
        System.out.println("我是无参构造方法");
    }
​
    @Autowired
    public void setUser(User user) {
        System.out.println("set方法注入");
        this.user = user;
    }
​
    public void afterPropertiesSet() throws Exception {
        System.out.println("初始化");
    }
}
​
我是无参构造方法
我是后置
set方法注入
初始化
    
    @Component
public class UserService implements InitializingBean {
​
    private User user;
​
    @PostConstruct
    public void xxx(){
​
        System.out.println("xxx");
    }
​
    public UserService() {
        System.out.println("我是无参构造方法");
    }
​
    @Autowired
    public void setUser(User user) {
        System.out.println("set方法注入");
        this.user = user;
    }
​
    public void afterPropertiesSet() throws Exception {
        System.out.println("初始化");
    }
}
​
我是无参构造方法
我是后置
set方法注入
xxx
初始化
    
    @PostConstruct
    利用初始化前的这个注解,可以进行其他操作
    <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>javax.annotation-api</artifactId>
            <version>1.3.2</version>
        </dependency>

初始化会在Spring自动注入后面才会执行,我们可以在里面修改我们想修改的都可以

初始化前

 

   @PostConstruct
    public void xxx(){
​
        System.out.println("xxx");
    }
​
@Component
public class LLBeanPostProcess implements InstantiationAwareBeanPostProcessor {
​
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("userService")){
            System.out.println("初始化前");
        }
        return null;
    }
}
​
​
我是无参构造方法
set方法注入
初始化前
初始化
com.user.UserService@3439f68d
    
    
    @Component
public class LLBeanPostProcess implements InstantiationAwareBeanPostProcessor {
​
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("userService")){
            System.out.println("初始化前");
        }
        return bean;
    }
}
​
我是无参构造方法
set方法注入
初始化前
xxx
初始化
com.user.UserService@3439f68d

这里我们的xxx方法上面的注解就相当于一个postProcessBeforeInitialization

LLBeanPostProcess------>postProcessBeforeInitialization 当方法返回null时,这里就起到一个中断的作用,前面的实例化全部都做完了,如果返回一个bean对象,初始化前方法就会把bean对象传到下一个方法中!

@PostConstruct------>postProcessBeforeInitialization 前面有对象返回的时候才有效!

验证
​
@Component
public class LLBeanPostProcess implements InstantiationAwareBeanPostProcessor {
​
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("userService")){
            System.out.println("初始化前");
            for (Method method : bean.getClass().getMethods()) {
                if (method.isAnnotationPresent(PostConstruct.class)){
                    try {
                        method.invoke(bean);//如果这个方法上面有这个注解就再执行一次
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return bean;
    }
}
​
我是无参构造方法
set方法注入
初始化前
xxx
xxx
初始化
com.user.UserService@3439f68d
​

初始化后

 

  public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("userService")){
            System.out.println("初始化后");
        }
        return bean;
    }
    
我是无参构造方法
set方法注入
初始化前
xxx
xxx
初始化
初始化后
com.user.UserService@3439f68d

我们就可以在这里面进行多态代理,也就是AOP,下面我们来进行一下模拟

package com.user;
​
public interface UserInterface {
​
    public void test();
}
​
​
public class UserService implements InitializingBean ,UserInterface{
​
 public void test() {
        System.out.println("业务逻辑");
    }
}
​
public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
        if (beanName.equals("userService")){
            Object o = Proxy.newProxyInstance(bean.getClass().getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
                public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                    System.out.println("动态代理");
                    return null;
                }
            });
            return o;
        }
        return bean;
    }
    
public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
        UserInterface userService = (UserInterface) context.getBean("userService");
        userService.test();
    }

我是无参构造方法
set方法注入
初始化前
xxx
xxx
初始化
动态代理

​
//这个bean就时userService对象,我们在初始化后方法中可以讲这个bean对象替换掉,替换成我们这个动态代理的代理类,相当于狸猫换太子。我们想要先执行我们的代理逻辑,再执行传入的userService对象的对应的method方法。
​
 public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
        if (beanName.equals("userService")){
            Object o = Proxy.newProxyInstance(bean.getClass().getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
                public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                    System.out.println("代理逻辑1");
                    method.invoke(bean,objects);
                    System.out.println("代理逻辑2");
                    return null;
                }
            });
            return o;
        }
        return bean;
    }
    
我是无参构造方法
set方法注入
初始化前
xxx
xxx
初始化
代理逻辑1
业务逻辑
代理逻辑2
​

也是我们Spring实现aop的基本逻辑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值