网站建设提供了哪些栏目/百度一下官网入口
正常情况下,应用中的bean同spring容器关系如下图:
尽管应用bean是Spring容器创建并建立依赖关系,应用只需使用bean即可,因此对bean来说Spring容器就是无感知的(无侵入编程)。但是还是存在需求需要应用bean同Spring容器进行交互,以便利用容器的能力完成相关工作。本篇就是讲述应用Bean如何与容器进行交互的。
创建
Bean实例化详细过程
框架加载BeanDefiniation,初始化容器环境,然后进行Bean的实例化:
1、如果有实现BeanPostProcessor的bean,则优先创建;
2、框架选择合适的Bean构建函数,创建Bean对象;
3、框架设置Bean属性;
4、如果bean实现了Aware接口,则执行;
5、如果存在BeanPostProcessor类,则执行postProcessBeforeInitialization;
6、如果bean有初始化方法(@PostConstruct标注或xml配置),则执行;
7、如果Bean实现了InitializingBean接口,则会调用afterPropertiesSet方法;
8、如果存在BeanPostProcessor类,则执行postProcessAfterInitialization;
9、如果bean有SmartInitializingSingleton,则在所有单实例bean实例化后执行afterSingletonsInstantiated
上述过程中存在“如果”的地方,就意味着应用可与容器交互的地方。
BeanPostProcessor
BeanPostProcessor接口主要是在bean初始化前后,应用可加入自己处理。注意:该类是针对所有应用bean的,因此处理时可根据Bean类做处理。
示例代码如下:
@Component
public class DemoBeanPostProcessor implements BeanPostProcessor {ApplicationContext ctx;DemoBeanPostProcessor(){System.out.println("Spring DemoBeanPostProcessor contructing...");}//---------------------------------------------------------------------// Implementation of BeanPostProcessor interface//---------------------------------------------------------------------@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {// 可根据beanName 或 instanceof 针对性处理System.out.println("Spring DemoBeanPostProcessor postProcessBeforeInitialization "+beanName+": "+bean);return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("Spring DemoBeanPostProcessor postProcessAfterInitialization "+beanName+": "+bean);return bean;}
}
Aware
感知类接口(接口名称格式:xxxAware),让实现的类可以感知容器的某些能力。SF的依赖注入亮点之一就是所有的Bean实现时都不需要考虑运行时要如何注入Spring容器(就是无感知),Bean和Spring容器耦合度很低(就是无侵入编程)。实际开发的时候,有时Bean需要用到Spring容器本身的功能资源,就需要提供一种机制让Bean能意识到Spring容器到存在并能调用Spring所提供的资源,这个机制就是由Aware来实现的。示例代码如下:
@Component
public class DemoAware implements ApplicationContextAware{//ctx在初始化过程中通过Aware方式注入ApplicationContext ctx;//---------------------------------------------------------------------// Implementation of ApplicationContextAware interface//---------------------------------------------------------------------public void setApplicationContext(ApplicationContext applicationContext) throws BeansException{System.out.println("DemoAware set ApplicationContextAware");this.app = applicationContext;System.out.println(app);}
}
详见:https://blog.csdn.net/davidwkx/article/details/130790874
初始化方法(@PostConstruct)
bean的初始化方法在框架加载中会执行,标注初始化方法有两种:注解@PostConstruct或xml。
注解方式示例如下:
@PostConstructpublic void init() {System.out.println("DemoInteractiveInInitialing init"); }
xml方式配置如下:
<bean id = "demoInteractiveInInitialing " class="com.learnsf.demo.spring.DemoInteractiveInInitialing " init-method="init"></bean>
afterPropertiesSet
InitializingBean接口定义了方法afterPropertiesSet,表示在Bean的属性设置后执行。
示例代码如下:
@Component
public class DemoInitializingBean implements InitializingBean{//---------------------------------------------------------------------// Implementation of InitializingBean interface//---------------------------------------------------------------------public void afterPropertiesSet() {System.out.println("DemoInteractiveInInitialing afterPropertiesSet ");}}
afterSingletonsInstantiated
SmartInitializingSingleton接口定义了方法afterSingletonsInstantiated,表示所有单例bean初始化后执行。
示例代码如下:
@Component
public class DemoSmartInitializingSingleton implements SmartInitializingSingleton{//---------------------------------------------------------------------// Implementation of SmartInitializingSingleton interface//---------------------------------------------------------------------public void afterSingletonsInstantiated(){System.out.println("DemoSmartInitializingSingleton::SmartInitializingSingleton在该类构建后被触发执行");}
}
应用中
Aware
在bean初始化过程通过Aware方式获得相关容器资源,直接使用即可。
MethodInterceptor
通过实现接口MethodInterceptor,可在执行方法前后做其它处理。
示例代码如下:
@Component
public class ProxyInterceptor implements MethodInterceptor {private String className;private String methodName;@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {className=o.getClass().getName();methodName=methodProxy.getSuperName();//method.getName(); before();//调用被代理类的方法Object result = methodProxy.invokeSuper(o, objects);after();return result;}// 预处理方法private void before() {System.out.println(String.format("%s.%s before excute: [%s] ",this.className, this.methodName,new Date()));}// 后处理方法private void after() {System.out.println(String.format("%s.%s after excute: [%s] ",this.className, this.methodName, new Date()));}
}
AOP注解
通过AOP注解和实现完成所需工作。
销毁
bean销毁前,bean可以有两种方式介入:继承DisposableBean接口或@PreDestroy或xml模式配置。
DisposableBean / @PreDestroy
应用bean可在实现org.springframework.beans.factory.DisposableBean接口中完成销毁前工作。
@Component
@Scope("singleton")
public class DemoDisposableBean implements DisposableBean{//---------------------------------------------------------------------// Implementation of DisposableBean interface//---------------------------------------------------------------------@Overridepublic void destroy() throws Exception{System.out.println("DemoDisposableBean destory start... "); }@PreDestroypublic void preDestory() throws Exception{System.out.println("DemoDisposableBean @PreDestory start... "); }
}
xml配置
<bean id = "DemoDisposableBean" class="com.learnsf.demo.spring.DemoDisposableBean" destory-method="destroy"></bean>
destory()方法不生效原因
实际使用可能出现destory()方法不起作用,有以下原因导致:
1、bean的作用域必须是单例的(singleton),不能是prototype。
2、容器没有正常关闭:如果容器不在Servlet或者EJB容器中,需要手动调用ApplicationContext子类中的close()方法,去实现相应关闭的功能。
示例如下:
public class LearnMain {public static void main(String[] args) {//创建springframework容器,初始化文件为app.xmlApplicationContext context = new ClassPathXmlApplicationContext("app.xml");...//容器关闭才能执行bean。destory()方法((ClassPathXmlApplicationContext)context).close();}
}
特殊FactoryBean
大多数情况下,应用bean都由SF的BeanFactory实例化和管理。但如果应用有需要,可以通过的自己工厂bean(FactoryBean)创建bean。FactoryBean需实现接口FactoryBean或SmartFactoryBean,T就是FactoryBean要创建的Bean。
FactoryBean被容器加载后,然后执行getObject()获得bean,容器就完成使命了,也不再执行“Bean实例化详细过程”(见本文第一节)第三步开始的内容。
下面是一个FactoryBean实例:
@Component("studentFacoryBean")
public class StudentFacoryBean implements FactoryBean<Student>{private static final String STUDENT_NAME = "Zhangsan";public Student getObject() {Student student = new Student();student.setName(STUDENT_NAME);return student;}public Class<?> getObjectType() {return Student.class;}
}