Bean的生命周期就是从初始化开始,一直到Spring去销毁它的整个过程,大致分为是一个过程:
1.instantiate bean 对象实例化
2.populate properties 封装属性
3.如果Bean实现BeanNameAware执行setBeanName
4.如果Bean实现BeanFactory或者ApplicationContextAware设置工厂
setBeanFactory或者上下文对象setApplicationContext
5.如果存在类实现BeanPostProcessor(后处理Bean),执行postProcessBeforeInitalization
6.如果Bean实现InitializingBean执行afterProtiesSet
7.调用 指定初始化方法init
8.如果存在类实现BeanPostProcessor(处理Bean),执行postProcessAfterInitialization
9.执行业务处理
10.如果Bean实现DisposableBean执行destory
11.调用指定销毁方法 customerDestory
public class Person implements BeanNameAware , ApplicationContextAware , InitializingBean , DisposableBean {
private String name;
public void setName(String name) {
System.out.println("第二步:设置属性值");
this.name = name;
}
public void Run(){
System.out.println("第九步:执行对象自身的业务方法");
}
public Person(){
System.out.println("第一步:实例对象初始化");
}
public void init(){
System.out.println("第七步:对象初始化");
}
public void Beandestory(){
System.out.println("第十一步:对象自身的销毁方法");
}
@Override
public void setBeanName(String name) {
System.out.println("第三步:设置Bean的名称,让Bean了解在配置文件中它对应的ID 或者 name的值");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("第四步:了解工厂的信息");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("第六步:在对象属性设置之后执行");
}
@Override
public void destroy() throws Exception {
System.out.println("第十步:调用spring的destroy方法");
}
}
public class MyBean implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("第五步:初始化Bean之前执行");
return bean;
}
@Override
public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
System.out.println("第八步:初始化Bean之后执行");
return bean;
}
}
Bean完整的生命周期大概就包括这十一个部分,大部分的其实都不需要我们去关注,我们只需要关注Bean自定义的初始化和销毁以及业务流程这几个点。
在说到对象代理之前我们需要先了解一下什么是AOP,AOP就是面向切面编程。在传统的业务处理代码中,通常都会进行事务处理、日志记录等操作。虽然适用面向对象(OOP)可以通过组合或者继承的方式进行修改来实现代码重用,但这样做的话,如果某个功能需要分散到各个方法中去(比如产生特定日志),就会使得修改的工作量大大增加,效率低下,而且会大大提高程序的出错率。为了解决类似于这样的问题就可以使用AOP,采用横向抽取机制,将分散在各个方法中的重复代码提取出来,然后在程序编译或者运行时再将这些提取出来的代码应用到需要执行的地方。在进行这样的操作时就需要进行对象的代理。比如上文中说到的Bean生命周期中的第五步和第八步就使用了AOP的思想,可以对Bean进行增强处理。
如在初始化之后进行对象权限的判断增强,模拟代码如下
@Override
public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
System.out.println("第八步:初始化Bean之后执行");
if(beanName.equals("userDao")){
Object proxy = Proxy.newProxyInstance(MyBean.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(method.getName().equals("delete")){
System.out.println("检查是否获得权限+++++++********");
Object obj = method.invoke(bean,args);
return obj;
}else{
return method.invoke(bean,args);
}
}
});
return proxy;
}else{
return bean;
}
}
JDK的动态代理是通过java.lang.reflect.Proxy类来实现的,我们可以调用Proxy的newProxyInstance()方法来创建代理对象,对于使用业务接口的类Spring默认会使用JDK动态代理来实现AOP
接口UserDao
public interface UserDao {
public void update();
public void delete();
public void insert();
public void select();
}
实现类UserDaoImpl
public class UserDaoImpl implements UserDao{
@Override
public void update() {
System.out.println("对象更新完成========");
}
@Override
public void delete() {
System.out.println("对象删除完成========");
}
@Override
public void insert() {
System.out.println("对象插入完成========");
}
@Override
public void select() {
System.out.println("对象查找完成========");
}
}
动态代理UserDaoProxy
/*
* 动态代理方式
* 目标类必须实现一个或者多个接口
*/
public class UserDaoProxy implements InvocationHandler {
public UserDao userDao;
public Object createProxyObject(UserDao userDao){
this.userDao = userDao;
ClassLoader classLoader = UserDaoProxy.class.getClassLoader();
Class[] clazz = userDao.getClass().getInterfaces();
return Proxy.newProxyInstance(classLoader,clazz,this);
}
@Overr`在这里插入代码片`ide
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("动态代理前置增强处理=======查看当前是否获得权限");
Object obj = method.invoke(userDao,args);
System.out.println("动态代理后置增强处理=======输出当前操作完成日志");
return obj;
}
}
CGLIB原理:对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
UserDaoProxyCGLIB
/*
* 使用CGLIB进行代理
* 对指定的目标类生成一个子类,进行增强,如果目标类是final就无法实现了
*
*/
public class UserDaoProxyCGLIB implements MethodInterceptor {
public Object createProxy(Object target){
//创建一个动态类对象
Enhancer enhancer = new Enhancer();
//确定需要增强的类,设置该类的父类
enhancer.setSuperclass(target.getClass());
//添加回调函数
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("CGLIB动态代理前置增强+++++++++++++++++++++++++++++++++权限判定");
Object obj = methodProxy.invokeSuper(o,objects);
System.out.println("CGLIB动态代理后置增强+++++++++++++++++++++++++++++++++日志生成");
return obj;
}
}
JDK动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK动态代理,CGLIB是针对类来实现代理的CGLIB。