Bean的生命周期
零散知识点插播:java8接口支持默认实现方法(default),静态方法(static)
默认实现类可以被重写,调用接口默认实现可用Interface.super.xxx()调用。
静态方法可直接用接口调用Interface.xxx(),但是静态方法不可被重写
Bean创建的生命周期
对象实例化后没有经过AOP则和正常new对象一样,但如果经过AOP后则生成的是一个代理对象。
- 生成BeanDefinition
- 合并BeanDefinition
- 加载类
- 实例化前
- 推断构造方法
- 实例化
- BeanDefinition的后置处理
- 填充属性
- 执行Aware
- BeanNameAware
- BeanClassLoaderAware
- BeanFactoryAware
- 初始化前
- ApplicationContextAwareProcessor
- EnvironmentAware
- EmbeddedValue
- ApplicationContextAwareProcessor
Bean后置处理器BeanPostProcessor
实现接口BeanPostProcessor,该接口的方法是默认实现的。
所有的bean都会进入这个接口的方法。
@Component
public class DatumInitializationBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("初始化后 " + beanName + " " + bean);
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if ("user".equals(beanName)) {
User user = (User) bean;
user.setName("hello");
System.out.println("我已设置");
System.out.println("初始化前 " + beanName + " " + bean);
return user;
}
System.out.println("初始化前 " + beanName + " " + bean);
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
User user = context.getBean("user", User.class);
System.out.println(user);
}
@ComponentScan("com.datum")
public class Config {
public Config() {
System.out.println("Config构造函数");
}
}
打印结果:
初始化前 config com.datum.Config@42d8062c
初始化后 config com.datum.Config@42d8062c
User初始化
初始化前 user User{name=‘null’}
我已设置
初始化后 user User{name=‘hello’}
User{name=‘hello’}
首先config对象产生后进入后置方法的before和after方法,再生成user对象进入后置处理器的before和after方法
后置处理器实现注解赋值
注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Datum {
String value();
}
User类
@Component
public class User {
@Datum("hello")//这个地方使用注解,将注解的值赋给这个成员变量
private String name;
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
public User() {
System.out.println("User构造函数");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
实现BeanPostProcessor接口,重写after方法
@Component
public class DatumInitializationBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("初始化前 " + beanName + " " + bean);
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
Class<?> clazz = bean.getClass();
Field[] declaredFields = clazz.getDeclaredFields();
for (Field field : declaredFields) {
if (field.isAnnotationPresent(Datum.class)) {
Datum annotation = field.getAnnotation(Datum.class);
String value = annotation.value();
try {
String name = field.getName();
Method setName = clazz.getMethod("set"+ name.substring(0,1).toUpperCase()+name.substring(1), String.class);
setName.invoke(bean, value);
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
System.out.println("初始化后 " + beanName + " " + bean);
return bean;
}
}
System.out.println("初始化后 " + beanName + " " + bean);
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
}
打印内容:
Config构造函数
初始化前 config com.datum.Config@42d8062c
初始化后 config com.datum.Config@42d8062c
User构造函数
初始化前 user User{name=‘null’}
初始化后 user User{name=‘hello’}
User{name=‘hello’}
Bean前置处理器(包含后置)InstantiationAwareBeanPostProcessor
InstantiationAwareBeanPostProcessor是BeanPostProcessor的子类
@Component
public class DatumInstantiationPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("实例化前 类名"+beanClass.getName());
if ("user".equals(beanName)) {
return new User();
}
return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass, beanName);
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("实例化后 类名"+bean.getClass().getName());
return InstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName);
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
return InstantiationAwareBeanPostProcessor.super.postProcessProperties(pvs, bean, beanName);
}
}
当实例化前返回一个对象后将不再调用实例化后的方法
打印结果:
实例化前 类名com.datum.Config
Config构造函数
实例化后 类名com.datum.Config
初始化前 config com.datum.Config@cb0ed20
初始化后 config com.datum.Config@cb0ed20
实例化前 类名com.datum.User
User构造函数
初始化后 user User{name=‘hello’}
User{name=‘hello’}
config类遵循 实例化前-实例化-实例化后-初始化前-初始化后
user类遵循 实例化前-实例化-初始化后
貌似这里user在实例化前返回一个实体类之后就不再执行实例化后和初始化前的方法。
探究bean的整个创建过程
Person类
@Component
public class Person {
private User user;
public Person() {
System.out.println("空参构造函数");
}
public Person(User user,User user1) {
System.out.println("两个个参数构造函数");
this.user = user;
}
public Person(User user) {
System.out.println("一个参数构造函数");
this.user = user;
}
@Autowired
public void setUser(User user) {
System.out.println("set方法注入user");
this.user = user;
}
@Override
public String toString() {
return "Person{" +
"user=" + user +
'}';
}
}
User类
public class User {
@Datum("hello")
private String name;
// static {
// System.out.println("静态代码块");
// }
// {
// System.out.println("代码块");
// }
public User() {
System.out.println("User构造函数");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
Config类
@ComponentScan("com.bean")
public class Config {
public Config() {
System.out.println("Config构造函数");
}
@Bean
public User user() {
System.out.println("user准备生成");
return new User();
}
@Bean
public User user1() {
System.out.println("user1准备生成");
return new User();
}
}
测试类
public class PostProcessorTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
User user = context.getBean("user", User.class);
System.out.println(user);
Person person = context.getBean("person", Person.class);
System.out.println(person);
}
}
打印结果
实例化前 类名com.bean.Config
Config构造函数
实例化后 类名com.bean.Config 实例化后的实例 com.bean.Config@2db7a79b
初始化前 config com.bean.Config@2db7a79b
初始化后 config com.bean.Config@2db7a79b
实例化前 类名com.bean.Person
空参构造函数
实例化后 类名com.bean.Person 实例化后的实例 Person{user=null}
实例化前 类名com.bean.User
user准备生成
User构造函数
实例化后 类名com.bean.User 实例化后的实例 User{name=‘null’}
初始化前 user User{name=‘null’}
初始化后 user User{name=‘hello’}
set方法注入user
初始化前 person Person{user=User{name=‘hello’}}
初始化后 person Person{user=User{name=‘hello’}}
实例化前 类名com.bean.User
user1准备生成
User构造函数
实例化后 类名com.bean.User 实例化后的实例 User{name=‘null’}
初始化前 user1 User{name=‘null’}
初始化后 user1 User{name=‘hello’}
User{name=‘hello’}
Person{user=User{name=‘hello’}}
由打印结果得出结论
Person完成实例化后,即开始创造出参数User实例,然后通过set方式(在Person类上加了@Autowired)注入User实例。
一个bean的生产过程:实例化前-构造函数-实例化后-属性填充-初始化前-初始化后。
public boolean postProcessAfterInstantiation(Object bean, String beanName)方法
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("实例化后 类名"+bean.getClass().getName()+" 实例化后的实例 "+bean);
// return InstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName);
return false;
}
InstantiationAwareBeanPostProcessor接口下的postProcessAfterInstantiation(Object bean, String beanName)方法返回值为boolean,可以在这个方法中对类最一些操作,操作完成后再进行spring与否可以自己决定。
返回true表示继续spring的逻辑(即上面代码的@Autowired),false即放弃spring的逻辑。
将返回值设置为false后打印结果:
实例化前 类名com.bean.Config
Config构造函数
实例化后 类名com.bean.Config 实例化后的实例 com.bean.Config@2db7a79b
初始化前 config com.bean.Config@2db7a79b
初始化后 config com.bean.Config@2db7a79b
实例化前 类名com.bean.Person
空参构造函数
实例化后 类名com.bean.Person 实例化后的实例 Person{user=null}
初始化前 person Person{user=null}
初始化后 person Person{user=null}
实例化前 类名com.bean.User
user准备生成
User构造函数
实例化后 类名com.bean.User 实例化后的实例 User{name=‘null’}
初始化前 user User{name=‘null’}
初始化后 user User{name=‘hello’}
实例化前 类名com.bean.User
user1准备生成
User构造函数
实例化后 类名com.bean.User 实例化后的实例 User{name=‘null’}
初始化前 user1 User{name=‘null’}
初始化后 user1 User{name=‘hello’}
User{name=‘hello’}
Person{user=null}
可以看出spring并没有去执行Person类中的setUser()方法。
即我们最后得到的bean中的user=null。
InitializingBean接口(初始化时操作对象)
bean对象继承InitializingBean接口后实现方法public void afterPropertiesSet() throws Exception
该方法用于在bean初始化的时候对当前bean(在此方法中操作bean使用this)进行操作。
@Component
public class Person implements InitializingBean {
private User user;
public Person() {
System.out.println("空参构造函数");
}
public Person(User user,User user1) {
System.out.println("两个个参数构造函数");
this.user = user;
}
public Person(User user) {
System.out.println("一个参数构造函数");
this.user = user;
}
@Autowired
public void setUser(User user) {
System.out.println("set方法注入user");
this.user = user;
}
@Override
public String toString() {
return "Person{" +
"user=" + user +
'}';
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println(this + "属性设置之后执行的方法");
System.out.println("Person初始化-属性设置之后");
}
}
public class User implements InitializingBean {
@Datum("hello")
private String name;
// static {
// System.out.println("静态代码块");
// }
// {
// System.out.println("代码块");
// }
public User() {
System.out.println("User构造函数");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println(this + "属性设置之后执行的方法");
System.out.println("User初始化-属性设置之后执行的方法");
}
}
打印结果:
实例化前 类名com.bean.Config
Config构造函数
实例化后 类名com.bean.Config 实例化后的实例 com.bean.Config@8646db9
初始化前 config com.bean.Config@8646db9
初始化后 config com.bean.Config@8646db9
实例化前 类名com.bean.Person
空参构造函数
实例化后 类名com.bean.Person 实例化后的实例 Person{user=null}
实例化前 类名com.bean.User
user准备生成
User构造函数
实例化后 类名com.bean.User 实例化后的实例 User{name=‘null’}
初始化前 user User{name=‘null’}
User{name=‘null’}属性设置之后执行的方法
User初始化-属性设置之后执行的方法
初始化后 user User{name=‘hello’}
set方法注入user
初始化前 person Person{user=User{name=‘hello’}}
Person{user=User{name=‘hello’}}属性设置之后执行的方法
Person初始化-属性设置之后
初始化后 person Person{user=User{name=‘hello’}}
User{name=‘hello’}
Person{user=User{name=‘hello’}}
可以看出当spring自动注入后才会执行实现该接口的方法
一般使用该方法进行验证该bean的一些属性是否验证正确
@PostConstruct注解
是javax包下的注解,它执行顺序是构造方法,@Autowired,执行@PostConstruct注解下的方法,再执行实现该接口的方法
但是当初始化前是返回null,则@PostConstruct注解失效,因为这个注解相当于一个PostProcessor,我们自己通过继承PostProcessor接口的类的初始化前做完了工作再将bean传给该注解的PostProcessor,但是你初始化的时候返回一个null,就不再传给该注解的PostProcessor,则该注解不生效。
此时这个注解的原理可以理解为这个注解的PostProcessor的初始化前方法判断这个bean的方法上是否有@PostConstruct方法,有的化就执行该方法。
初始化后模拟AOP
首先写一个自定以的接口
public interface ProxyInterfaceTest {
void proxyMethod();
}
让Person对象实现该接口
@Component
public class Person implements InitializingBean,ProxyInterfaceTest {
private User user;
public Person() {
System.out.println("空参构造函数");
}
public Person(User user,User user1) {
System.out.println("两个个参数构造函数");
this.user = user;
}
public Person(User user) {
System.out.println("一个参数构造函数");
this.user = user;
}
@Autowired
public void setUser(User user) {
System.out.println("set方法注入user");
this.user = user;
}
@Override
public String toString() {
return "Person{" +
"user=" + user +
'}';
}
@PostConstruct
public void hello() {
System.out.println("Person类的@PostConstruct注解的方法执行");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println(this + "属性设置之后执行的方法");
System.out.println("Person初始化-属性设置之后");
}
@Override
public void proxyMethod() {
System.out.println("Person的业务逻辑");
}
}
在初始化后进行代理该接口的逻辑
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
Class<?> clazz = bean.getClass();
Field[] declaredFields = clazz.getDeclaredFields();
for (Field field : declaredFields) {
if (field.isAnnotationPresent(Datum.class)) {
Datum annotation = field.getAnnotation(Datum.class);
String value = annotation.value();
try {
String name = field.getName();
Method setName = clazz.getMethod("set"+ name.substring(0,1).toUpperCase()+name.substring(1), String.class);
setName.invoke(bean, value);
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
System.out.println("初始化后 " + beanName + " " + bean);
return bean;
}
}
Object o = Proxy.newProxyInstance(bean.getClass().getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理 invoke 的代理逻辑");
method.invoke(bean, args);
return null;
}
});
if ("person".equals(beanName)) {
return o;
}
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
通过getBean获取该接口的实例
ProxyInterfaceTest person1 = (ProxyInterfaceTest) context.getBean(“person”);
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
User user = context.getBean("user", User.class);
System.out.println(user);
ProxyInterfaceTest person1 = (ProxyInterfaceTest) context.getBean("person");
person1.proxyMethod();
Person person = context.getBean("person", Person.class);
System.out.println(person);
}
打印结果:
实例化前 类名com.bean.Config
Config构造函数
实例化后 类名com.bean.Config 实例化后的实例 com.bean.Config@37374a5e
初始化前 config com.bean.Config@37374a5e
实例化前 类名com.bean.Person
空参构造函数
实例化后 类名com.bean.Person 实例化后的实例 Person{user=null}
实例化前 类名com.bean.User
user准备生成
User构造函数
实例化后 类名com.bean.User 实例化后的实例 User{name=‘null’}
初始化前 user User{name=‘null’}
User类的@PostConstruct注解的方法执行
User{name=‘null’}属性设置之后执行的方法
User初始化-属性设置之后执行的方法
初始化后 user User{name=‘hello’}
set方法注入user
初始化前 person Person{user=User{name=‘hello’}}
Person类的@PostConstruct注解的方法执行
Person{user=User{name=‘hello’}}属性设置之后执行的方法
Person初始化-属性设置之后
User{name=‘hello’}
代理 invoke 的代理逻辑
Person的业务逻辑