EDITORIAL words
Intended audience: those with some experience, this is not for beginners, because it may not understand what I'm saying
Article thinking: do not start a blog just like other articles like, Bean's life cycle, source code interpretation (you stick a bunch of source code). Personally feel should be driven by the question, why is the emergence of BeanFactory, why is there life cycle.
text
We started using the bean are simple bean, such as vo, po, entity, dto, so we are playing
XXEntity xxEntity = new XXEntity();
xxEntity.setPropA("字符串");
There may be a behind a complex bean, which has as an object property, you need to set the value at the time of construction or post-construction (Example only, not seriously), as
// 构建序列化实例,这里 Serializable 是接口,使用接口的好处是在使用别的序列化时,不需要修改 jedis 类
Serializable fastJsonSerizlizable = new FastJsonSerizlizable();
// 构建目标 jedis 实例 ,需要先构建序列化对象
Jedis jedis = new Jedis();
jedis.setSerializable(fastJsonSerizlizable);
Then came serviceA serviceB classes and classes that need to use redis, I can not go to jedis example of the process of writing it again in each class which, when experienced students will write a class tool to create jedis, like this
public BeanUtil {
// 可以把创建序列化单拿出来,因为除了 redis 需要序列化之外,kafka 也需要序列化
public static Serializable createSerializable(){
return new FastJsonSerizlizable();
}
public static Jedis createJedis(){
Jedis jedis = new Jedis();
jedis.setSerializable(createSerializable());
return jedis;
}
}
// 这里我 serviceA,serviceB 都可以使用 createJedis 来直接获取 jedis 实例 ,而不需要关心创建细节,使用哪个序列化等问题
There are several problems in the code above
- Jedis is created every time you use an object, and each individual will jedis subject to a Serializable object, but fastJson serialization and jedis types of things are just tools, an instance of enough already.
- Jedis can not be configured
- Not allow users to create BeanUtil instance, improved code as follows
public BeanUtil {
// 禁用 BeanUtil 构建
private BeanUtil(){}
// 这里我们可以使用 bean 的全路径 => bean 实例来缓存 bean
static Map<String,Object> beansCache = new ConcurrentHashMap<String,Object>();
static{
// 初始化时,在内容缓存这些 bean 的实例,因为 jedis 依赖于 serializable ,需要需要先创建 serializable
Serializable serializable = createSerializable();
beansCache.put(Serializable.class.getSimpleName(),serializable);
Jedis jedis = createJedis();
beansCache.put(jedis.class.getSimpleName(),jedis);
}
static Serializable createSerializable(String type){
Serializable serializable = beansCache.get("serializable");
if(serializable != null)return serializable;
switch(type){
case "kryo": // kryo 不能用单例,请忽略本问题,示例而已
return new KryoSerializable();
case "protostuff":
return new protostuffSerializable();
default:
return new FastJsonSerizlizable();
}
}
static Jedis createJedis(String serializableType){
Jedis jedis = new Jedis();
Serializable serializable = beansCache.get("serializable");
jedis.setSerializable(serializable);
return jedis;
}
//然后对外提供获取 Bean 的方法
public static Object getBean(String beanName){
return beansCache.get(beanName);
}
public static T getBean(Class<T> type){
return beansCache.get(type.getSimpleName());
}
}
But if the writing of this class is Xiao Ming, after a period of time this class will be initialized operate a large number of createXx and XX, and the degree of dependence is very complex, then Xiao Ming think it is time to optimize the wave, so Xiao Ming thought One solution, defines a syntax xml
Bean tag used to define a bean, bean each has a unique id information, using the property to define its properties, if it is complicated to use REF attribute, parsing the xml obtain a complete dependency graph bean
<beans>
<bean id="serializable" class="com.xx.FastJsonSerizlizable" />
<bean id="jedis" class="com.xx.Jedis">
<property name="host" value="localhost" />
<property name="serializable" ref="serializable"/>
</bean>
</beans>
Then there is a dependency problem, I created jedis first create serializable, but xml bean defined serializable is written in the front of the file, Xiao Ming thought of a way, first with pre-existing string ref, all put a bean definition, like this
Map<String,BeanDefinition> beanDefinitions = new HashMap();
Then parse it into a dependency tree, so that you can construct the first leaves, then the object is constructed layer by layer, but there is also a tricky situation, and that is a circular dependency
root
|-jedis
|- serializable
What it is a circular dependency, the simplest A depends on B, B is dependent on A, middle or last more dependent on the formation of a ring, ABCA
The most original solution is such that we can first use the constructor to create them all out, you can not be there with their constructors, and then set the target set by property values. Therefore, the configurations of the injection, the property by way of circular dependency can be resolved.
Then our BeanUtil become such, can not think of a utility class called instead entity classes Factory
public BeanFactory {
Map<String,BeanDefinition> beanDefinitions = new HashMap();
// 这里我们可以使用 bean 的全路径 => bean 实例来缓存 bean
Map<String,Object> beansCache = new ConcurrentHashMap<String,Object>();
{
// 加载 xml bean 配置文件
beanDefinitions = loadXml(contextConfigurations:String []);
//实例化所有 bean
beansCache = instanceBeans(beanDefinitions);
}
//然后对外提供获取 Bean 的方法
public Object getBean(String beanName){
return beansCache.get(beanName);
}
public T getBean(Class<T> type){
return beansCache.get(type.getSimpleName());
}
}
This seems to have perfectly adequate, but this time programmer A question I need to initialize when one of my classes, I want to get some resources such as connection, files, resources, and want to reclaim resources at class destruction, However, according to the above did not have any way to do it.
Little said, this is easy to handle, I offer several interfaces to you, you realize what I'll be when the instance of the Bean, if you find you have to implement an interface in the corresponding process where I can help you call it, so Xiaoming added two interfaces
public interface InitializingBean{
void afterPropertiesSet() throws Exception;
}
public interface DisposableBean{
void destroy() throws Exception;
}
A programmer problem is resolved, then the programmer B said, Is there a way, can intercept all of the initialization process Bean, rather than my current class, I want every service into a proxy class, I want to add transaction service in the method.
Little said, Well, I put the bean properties are injected over, and then to the bean to you, you decorate the bean and then back to me, so Xiao Ming provided out of such an interface, and is initialized before the bean initialization after, you can come to modify bean, do not pay attention, this is for the global, not your personal bean, to do the filtering operation
public interface BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException ;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException
}
C programmers and ask questions at this time, I created a BeanA but how I can get BeanC ah, I want to see some of the properties of c.
Fiction that really annoying, I just put the map gave Hello, no, I gave Hello BeanFactory, and so with this interface
public interface BeanFactoryAware{
void setBeanFactory(BeanFactory beanUtil);
}
This will then D asked, when I setBeanFactory, and I created a global processor implemented, or are in the execution after the big head.
Under Little said, I'm finishing order of execution, we take a name, called the bean's life cycle, the way and then provide several practical interface, the bean name I have not told How about you, so finishing the life cycle of the following
反射创建 Bean
填充对象属性
BeanNameAware.setBeanName();
BeanFactoryAware.setBeanFactory ();
BeanPostProcessor.postProcessBeforeInitialization(); 多个
InitializingBean.afterPropertiesSet()
BeanPostProcessor.postProcessAfterInitialization(); 多个
DisposableBean.destory()
E said the programmer, xml configuration too much trouble, jdk1.5 do not have a comment, I like to add a logo on, you scan my class, help me create an instance of chanting
Then I need, I add a logo on the property, you can also find dependent classes depending on the type, and then created the corresponding instance, help me put the value into them just fine, if the process of creating this kind of comparison complex, to create my own, then I put it back to you, I define a method, add a logo Bean, you read into the container.
So Xiao Ming also added @Component
to represent the components @Bean
to represent the custom instance is created, @Autowired
to inject the object @PostConstruct
to perform the initialization class @PreDestroy
destroy class to do the work, the life cycle of the class become so
反射创建 Bean
填充对象属性
BeanNameAware.setBeanName();
BeanFactoryAware.setBeanFactory ();
BeanPostProcessor.postProcessBeforeInitialization(); 多个
PostConstruct
InitializingBean.afterPropertiesSet()
BeanPostProcessor.postProcessAfterInitialization(); 多个
PreDestroy
DisposableBean.destory()
But for compatibility with previous xml form, Xiao Ming then abstracted into the BeanFactory interface, providing getBean method, based on a single principle of duty, Bean BeanFactory should not resolve to do the work;
Then create an interface for loading Bean definition, there are two implementations XmlBeanRegistry, AnnotationBeanRegistry, loaded Bean defined after the merger, after taking into account also possible to add other registered bean ways, providing a one-time external interface
public interface BeanFactoryPostProcessor{
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
You can put your bean definitions written rules, instantiated as BeanDefinition I ask then send me a custom implementation can add your own custom bean into the container
Little promotion
Writing is not easy, I hope the support of open source software, and my gadgets, welcome to gitee point star, fork, put bug.
Excel common import and export, support Excel formulas
blog address: https://blog.csdn.net/sanri1993/article/details/100601578
gitee: https://gitee.com/sanri/sanri-excel-poi
Use the template code, the gadget generate code from the database, and some projects can often be used in the
blog address: https://blog.csdn.net/sanri1993/article/details/98664034
gitee: https://gitee.com/ sanri / sanri-tools-maven