Tiger-Painted cats write their own spring--dependency injection

Source: Internet
Author: User

Objective

In the article "Tiger Painting cat write their own spring" from scratch to tell and realize the following points

    • Declaring a configuration file that declares the class to be loaded using
    • Load configuration file, read configuration file
    • Parsing the configuration file, you need to convert the label declared in the configuration file to a class that fairy can recognize
    • Initializes a class that provides an instance of the class declared in the configuration file

In a nutshell: bean loading and instantiation is implemented without the help of spring containers

To fit the original intention of the Fairy name ( 东西不大,但是能量无穷 ), only a set of mechanisms to load the bean is not enough, so still need to follow the Tiger painting cat, perfect this little elf.

Spring's emergence in the many frameworks of Java enterprise development is inseparable from his shine of dependency injection (aka control reversal IOC) and aspect-oriented (AOP) . After fairy implemented the function of loading the instantiated bean, let's go one step further and see how dependency injection is implemented.

Dependency Injection

For example, the following is an introduction to dependency injection.
No dependency injection before we buy cabbage, we need to carry a basket to go to the market to pick and buy;
With the dependency injection, when we need the cabbage, the dish is in the basket and is already on your doorstep.
This is dependency injection.

For Fairy, if you want to implement dependency injection, you need to make some minor changes to the previous version of the Code.
Instead of changing the original Fairybean interface and implementing Class Fairybeanimpl to Fairydao interface and implementing class Fairydaoimpl, we need to add a new interface Fairyservice and implement class Fairyserviceimpl.
So, I believe you must understand that this is to use the dependency injection function.

Configuration

We still initialize the container in a way that reads the configuration file. Create a new configuration file Application-context-inject.xml

<beans>    <bean id="fairyService" class="com.jackie.fairy.bean.impl.FairyServiceImpl">        <property name="fairyDao" ref="fairyDao"></property>        <property name="lightColor" value="blue"></property>    </bean>    <bean id="fairyDao" class="com.jackie.fairy.bean.impl.FairyDaoImpl">    </bean></beans>

Meanwhile, we need fairyservice and Fairyserviceimpl.
Fairyservice

package com.jackie.fairy.bean;/** * Created by jackie on 17/11/25. */public interface FairyService {    void greet();    void fly();    void lighting();}

Fairyserviceimpl

Package Com.jackie.fairy.bean.impl;import Com.jackie.fairy.bean.fairydao;import com.jackie.fairy.bean.fairyservice;/** * Created by Jackie on 17/11/25.    */public class Fairyserviceimpl implements Fairyservice {private Fairydao Fairydao;    Private String Lightcolor;        Public Fairydao Getfairydao () {System.out.println ("===getfairydao===:" + fairydao.tostring ());    return Fairydao;        } public void Setfairydao (Fairydao Fairydao) {System.out.println ("===setfairydao===:" + fairydao.tostring ());    This.fairydao = Fairydao;    } public String Getlightcolor () {return lightcolor;    } public void Setlightcolor (String lightcolor) {this.lightcolor = Lightcolor;    } @Override public void greet () {fairydao.greet ();    } @Override public void Fly () {fairydao.fly (); } @Override public void Lighting () {System.out.println ('----------Hi, I am light Fairy. Exactly, "+ Lightcolor +" Color light fairy----------"); }}
    • Did not use @autowired to inject Fairydao, this is the set of spring
    • Add Fairydao as a member variable, adding setter and getter methods (subsequent injection use)
    • Add Fairyservice own Implementation method lighting, this is a glowing elf feature, the light-emitting properties of the elf depends on the lightcolor, this attribute needs to be injected, so there are corresponding setter and getter method
Upgrade Parser class

The Xmlreaderutil parser in the previous article can only parse such a configuration structure

<parent>    <child>    </child>    ...    <child>    </child><parent>

But we now need to support the configuration file as shown in the above configuration file, so you need to upgrade the parser class to support reading the property label of the child tag.
Prior to this, you need to create a new model PropertyDefinition for storing property values

  Package com.jackie.fairy.model;/** * Created by Jackie on 17/11/25. */public class PropertyDefinition {Priv    Ate String name;    Private String ref;    private String value;        Public propertydefinition (string name, string ref, String value) {this.name = name;        This.ref = ref;    This.value = value;    } public String GetName () {return name;    } public void SetName (String name) {this.name = name;    } public String GetRef () {return ref;    public void SetRef (String ref) {this.ref = ref;    } public String GetValue () {return value;    The public void SetValue (String value) {this.value = value;                 } @Override Public String toString () {return ' propertydefinition{' + ' name= ' "+ name + ' \ ' +    ", ref= '" + ref + ' \ ' + ", value= ' + value + ' \ ' + '} '; }}

At the same time, you need to include the list in the Beandefinition model , because the attribute value is attached to the beandefinition.

Xmlreaderutil Change the core code to

for (Iterator Iterator = Rootelement.elementiterator (); Iterator.hasnext ();)    {element element = (Element) Iterator.next ();    String id = element.attributevalue (constants.bean_id_name);    String clazz = Element.attributevalue (constants.bean_class_name);        Beandefinition beandefinition = new Beandefinition (ID, clazz); Traverse Property Label for (Iterator propertyiterator = Element.elementiterator (); Propertyiterator.hasnext ();)        {element propertyelement = (Element) Propertyiterator.next ();        String name = Propertyelement.attributevalue (constants.property_name_name);        String ref = Propertyelement.attributevalue (Constants.property_ref_name);        String value = Propertyelement.attributevalue (Constants.property_value_name);    Propertydefinitions.add (New propertydefinition (name, ref, value));    } beandefinition.setpropertydefinitions (Propertydefinitions);    Beandefinitions.add (beandefinition); Empty the Propertydefinitions collection because some beans do not have a property tag PropertyDefInitions = Lists.newarraylist (); }

That is, the parsing and storage of attribute tags is added, and detailed code can be viewed on GitHub projects.

Implementing a Dependency Injection function

To add a function that implements dependency injection in Fairyapplicationcontext, the main idea is to find a class that needs to be injected (the fairyservice here), to identify the classes to which to rely on the injection (Fairydao here), and with the reflection mechanism, The Fairydao is injected into the fairyservice by the setter method.

Injectobject ()

private void Injectobject () {for (beandefinition beandefinition:beandefinitions) {Object bean = Instancebean        S.get (Beandefinition.getid ());                if (bean! = null) {try {BeanInfo BeanInfo = Introspector.getbeaninfo (Bean.getclass ()); /** * BeanInfo to get the property descriptor (PropertyDescriptor) * This property descriptor can be used to obtain a property corresponding to the Getter/sette                 R method * Then we can invoke these methods through the reflection mechanism.                */propertydescriptor[] propertydescriptors = Beaninfo.getpropertydescriptors (); For (PropertyDefinition propertyDefinition:beanDefinition.getPropertyDefinitions ()) {for (Propertyde                        Scriptor propertydescriptor:propertydescriptors) {//user-defined bean attributes are the same as Java-introspective bean property names                            if (Stringutils.equals (Propertydescriptor.getname (), Propertydefinition.getname ())) { Get setter Methods Method setter =Propertydescriptor.getwritemethod ();                                if (setter! = null) {Object value = null; if (Stringutils.isnotempty (Propertydefinition.getref ())) {//based on the name of the bean is obtained in Instancebeans                                Takes the specified object value = Instancebeans.get (Propertydefinition.getref ()); } else {value = Convertutils.convert (Propertydefinition.getvalue (), Propertyd                                Escriptor.getpropertytype ());                                }////Ensure that the setter method can access the private setter.setaccessible (true); try {//Inject Reference object into property setter.i                                Nvoke (bean, value);        } catch (Exception e) {log.error ("Invoke Setter.invoke failed", e);                        }} break; }}}} catch (Exception e) {log.error ("Invoke Getbean failed            ", e); }        }    }}
    • Using Java introspection to get the setter and getter methods for the Bean's various properties
    • The setter method is invoked using reflection to inject it into the Fairyservice class
Test

Writing test Code

/** * bean依赖注入 */FairyApplicationContext autowiredApplicationContext =        new FairyApplicationContext("application-context-inject.xml");FairyService fairyService = (FairyService) autowiredApplicationContext.getBean("fairyService");fairyService.greet();fairyService.lighting();

Get results

===setFairyDao===: [email protected]Hi, I am fairy----------Hi, I am light fairy. Exactly, blue color light fairy----------

The first line of the print result is triggered when the print is executed by reflection setter.invoke(bean, value); .

At this point, we have implemented a dependency injection function for fairy, the project address
Https://github.com/DMinerJackie/fairy

Project structure

Fairy Project Change Counting
    • Add a FairyApplicationContext(String configLocation) constructor, the default loaded configuration file is XML format
    • Add a JSON profile parser to parse the JSON-formatted configuration file and load the bean
    • Reconstruct the test bean, change the interface Fairybean to Fairydao, add Fairyservice interface and implement class, facilitate the use case test of this paper
    • Upgrade Xmlreaderutil to support the parsing of the bean's self-tagging property
    • Add Dependency injection function, user implements dependency injection function
    • Add a propertydefinition model for storing property value

If you feel that reading this article is helpful to you, please click " recommend " button, your " recommendation " will be my biggest writing motivation! If you want to keep an eye on my article, please scan the QR code, follow Jackiezheng's public number, I will push my article to you and share with you the high-quality articles I have read every day.

Tiger-Painted cats write their own spring--dependency injection

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.