重温Spring之IoC(二)


有点长 有点杂 加油 🦆 🦆


实例化Bean方法

构造方法

无参构造

  • xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user" class="org.example.User">
        <property name="name" value="xixi"></property>
        <property name="gender" value="0"></property>
    </bean>
</beans>
  • java
public class User {
    private  String name;
    private  String gender;

    public User() {
        System.out.println("constructor User()");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                '}';
    }
}
  • text
    @Test
    public void Test() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user = ac.getBean(User.class);
        System.out.println(user.toString());

    }
  • console
constructor User()
User{name='xixi', gender='0'}

有参构造

  • xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user2" class="org.example.User">
        <constructor-arg name="name1" value="xixi"></constructor-arg>
        <constructor-arg name="gender1" value="0"></constructor-arg>
    </bean>
</beans>
  • java
package org.example;

public class User {
    private  String name;
    private  String gender;

    public User() {
        System.out.println("constructor User()");
    }

    public User(String name1, String gender1) {
        System.out.println("constructor User(String,String)");
        this.name = name1;
        this.gender = gender1;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                '}';
    }
}

  • test
    @Test
    public void Test() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user = ac.getBean(User.class);
        System.out.println(user.toString());

    }

console

constructor User(String,String)
User{name='xixi', gender='0'}

静态工厂(静态方法)

无参

  • xml
<bean id="user" class="org.example.UserBeanFactory" factory-method="getUserBean">
    <property name="gender" value="0"></property>
    <property name="name" value="xixi"></property>
 </bean>
  • java
public class UserBeanFactory {
    public static User getUserBean(){
        return new User();
    }
}
  • test
    @Test
    public void Test() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        //User bean = (User)ac.getBean("user");
        User bean = (User)ac.getBean(User.class);
        System.out.println(bean);
    }
  • console
constructor User()
User{name='xixi', gender='0'}

有参

  • xml
<bean id="user" class="org.example.UserBeanFactory" factory-method="getUserBean">
    <constructor-arg name="gender" value="0"></constructor-arg>
    <constructor-arg name="nm" value="xixi"></constructor-arg>
</bean>
  • java
    public static User getUserBean(String nm,String gender){
        System.out.println(" getUserBean(String nm,String gender)");
        User user =  new User();
        user.setGender(gender);
        user.setName(nm);
        return user;
    }
  • test
    @Test
    public void Test() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

        User bean = (User)ac.getBean(User.class);
        System.out.println(bean);
    }
  • console
getUserBean(String nm,String gender)
constructor User()
User{name='xixi', gender='0'}

Calendar.getInstance(),System.getenv("JAVA_HOME")

实例工厂(非静态方法)

无参

  • xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


    <bean id="userBeanFactory" class="org.example.UserBeanFactory">
    </bean>

    <!-- factory-bean:工厂对象, factory-method:工厂方法-->
    <bean id="userBean" factory-bean="userBeanFactory" factory-method="getUserBean">
        <property name="name" value="xixi"></property>
        <property name="gender" value="0"></property>
    </bean>
</beans>
  • java
public class UserBeanFactory {
    public  User getUserBean(){
        return new User();
    }
}
  • test
    @Test
    public void Test() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

        User bean = (User) ac.getBean("userBean");

        User bean1 = (User) ac.getBean(User.class);
        System.out.println(bean.toString());
        System.out.println(bean1.equals(bean));
        System.out.println(bean1.toString());
    }
  • console
constructor User()
User{name='xixi', gender='0'}
true
User{name='xixi', gender='0'}

有参

  • xml
  <bean id="userBean" factory-bean="userBeanFactory" factory-method="getUserBean">
        <!--        <property name="name" value="xixi"></property>-->
        <!--        <property name="gender" value="0"></property>-->
        <constructor-arg name="nm" value="xixi"></constructor-arg>
        <constructor-arg name="gender" value="0"></constructor-arg>
  </bean>
  • java
public  User getUserBean(String nm,String gender){
        System.out.println(" getUserBean(String nm,String gender)");
        User user =  new User();
        user.setGender(gender);
        user.setName(nm);
        return user;
    }
  • test
    @Test
    public void Test() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

        User bean = (User) ac.getBean("userBean");

        User bean1 = (User) ac.getBean(User.class);
        System.out.println(bean.toString());
        System.out.println(bean1.equals(bean));
        System.out.println(bean1.toString());
    }
  • console
getUserBean(String nm,String gender)
constructor User()
User{name='xixi', gender='0'}
true
User{name='xixi', gender='0'}

练习

练习1:java获取时间

        Calendar calendar = Calendar.getInstance();
        Date date = calendar.getTime();


  • IoC容器获取
    <bean id="calendar" class="java.util.Calendar" factory-method="getInstance"></bean>
    <bean id="date" factory-bean="calendar" factory-method="getTime" ></bean>
 Date bean = (Date) ac.getBean("date");

练习2:数据库连接

  • java获取链接
        Class.forName("com.mysql.jdbc.Driver");
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/XI?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8","root","1234");
        PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM USER");


  • IoC获取
   <bean class="java.lang.Class" factory-method="forName">
        <constructor-arg name="className" value="com.mysql.jdbc.Driver"></constructor-arg>
    </bean>

    <bean id="connection" class="java.sql.DriverManager" factory-method="getConnection">
        <constructor-arg name="url" value="jdbc:mysql://localhost:3306/XI?serverTimezone=UTC"></constructor-arg>
        <constructor-arg name="user" value="root"></constructor-arg>
        <constructor-arg name="password" value="1234"></constructor-arg>
    </bean>

    <bean id="preparedStatement" factory-bean="connection" factory-method="prepareStatement">
        <constructor-arg name="sql" value="SELECT * FROM USER"></constructor-arg>
    </bean>
 PreparedStatement ps =  (PreparedStatement)ac.getBean("preparedStatement");


实例化bean时机

ClassPathXmlApplicationContext

// 默认预先实例化
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
<!-- lazy-init="true" 懒实例化 
     lazy-init="false" 预先实例化 -->
<bean class="org.example.User" lazy-init="true"></bean>


BeanFactory

// 懒实例化 
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
<bean class="org.example.User" ></bean>


Bean作用域配置

  • scope
  • singleton 单例(单例中的全局属性在多线程中不安全)
  • prototype 非单例
  • request 同一个请求中单例
  • session 同一个会话中单例


Bean继承配置

  • 不同子类继承同一个bean
    <bean id="common" abstract="true">
        <property name="name" value="XI"></property>
        <property name="gender" value="boy"></property>
    </bean>

    <bean id="bean1" class="org.example.Bean1" parent="common">
        <property name="tag" value="知行合一"></property>
    </bean>

    <bean id="bean2" class="org.example.Bean2" parent="common">
        <property name="score" value="100"></property>
    </bean>
  • 相同子类继承同一个bean
    <bean id="common1" class="org.example.Bean1">
        <property name="name" value="XI"></property>
        <property name="gender" value="boy"></property>
    </bean>
    
    <bean id="bean3"  parent="common1">
        <property name="tag" value="知行合一"></property>
    </bean>


    <bean id="bean4"  parent="common1">
        <property name="tag" value="善于思考"></property>
    </bean>


自动装配

(仅适用于一个bean引用其他bean)

  • autowire=byName/byType/constructor/no/default

constructor:先byName后byType

  • 并非所有类都交由Ioc容器进行管理


在一个自身不在IoC容器的bean中获取IoC容器

  • 添加实现接口ApplicationContextAware的工具类
public class ApplicationContextHolder implements ApplicationContextAware {

    private static ApplicationContext ac;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println(applicationContext);
        ac = applicationContext;
    }
    
    public static Object getBean(String beanName){
        return ac.getBean(beanName);
    }
    
    public static <T> T getBean(Class<T> clazz){
        return ac.getBean(clazz);
    }
}
  • 到IoC容器中
    <bean id="user" class="org.example.User"></bean>
    <bean class="org.example.ApplicationContextHolder"></bean>
  • test
    @Test
    public void Test() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

        System.out.println(ApplicationContextHolder.getBean("user"));

        System.out.println(ApplicationContextHolder.getBean(User.class));

    }


FactoryBean

  • bean类型
    1.普通Bean 返回bean本身的对象
    2.工厂Bean 返回任意类型
  • 实现FactoryBean接口,返回的bean类型是getObject()返回的类型

public class PreparedStatementFactoryBean implements FactoryBean<PreparedStatement> {
    /**
     * 生成实例的过程
     * @return
     * @throws Exception
     */
    @Override
    public PreparedStatement getObject() throws Exception {
        Class.forName("com.mysql.cj.jdbc.Driver");
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/XI?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8","root","1234");
        PreparedStatement ps = connection.prepareStatement("SELECT * FROM USER");
        return ps;
    }

    /**
     * 生成实例类型,此方法为兼容老版本的代码
     * @return:实例类型
     */
    @Override
    public Class<?> getObjectType() {
        return PreparedStatement.class;
    }

    /**
     * 是否单例
     * true:单例,false:非单例
     * @return
     */
    @Override
    public boolean isSingleton() {
        return false;
    }
}
  • 放到IoC容器中
    <bean id="ps" class="org.example.PreparedStatementFactoryBean"></bean>
  • test
    @Test
    public void Test() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        System.out.println(ac.getBean("ps"));
    }
  • console
com.mysql.cj.jdbc.ClientPreparedStatement: SELECT * FROM USER


Resource

基本用法

根据文件文职不同,来快速获取文件资源

装配

    <bean id="myResources" class="org.example.MyResources">
        <property name="resource" value="file:F:\itool\springframework\spring-ioc"></property>
        <!--<property name="resource" value="classpath:applicationContext.xml"></property>-->
    </bean>
  • test
    @Test
    public void Test() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

        MyResources myResources = (MyResources)ac.getBean(MyResources.class);
        Resource resource = myResources.getResource();
        System.out.println(resource.getFilename());
    }


后置处理器

Bean后置处理器 BeanPostProcessor

  • 时机:初始化方法之前/之后
    代码块->实例化->数据装配->初始化之前->初始化方法->初始化之后->就绪->使用->销毁方法->容器销毁
  • 使用:实现BeanPostProcessor接口,放置IoC容器
    

BeanFactory后置处理器 BeanFactoryPostProcessor

  • 时机:Bean创建之前
    BeanFactoryPostProcessor->代码块->实例化->数据装配->初始化之前->初始化方法->初始化之后->就绪->使用->销毁方法->容器销毁
  • eg:在容器中注册属性编辑器
    (属性编辑器:实现接口PropertyEditor或继承PropertyEditorSupport)

练习PropertyEditorSupport

  • eg
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean class="org.example.User"></bean>

    <bean id="bean1" class="org.example.Bean1" init-method="toString">
        <property name="user" value="[xixi-boy]"></property>
        <property name="tag" value="春和景明"></property>
    </bean>


    <bean class="org.example.MyBeanFactoryProcessor"></bean>
    <bean class="org.example.MyBeanPostProcessor"></bean>
</beans>
public class UserEditor extends PropertyEditorSupport {

    @Override
    public String getAsText() {
        return super.getAsText();
    }

    /**
     * 将text转化为User
     * @param text
     * @throws IllegalArgumentException
     */
    @Override
    public void setAsText(String text) throws IllegalArgumentException {
        Pattern pattern = Pattern.compile("\\[(.*)-(.*)\\]");
        Matcher matcher = pattern.matcher(text);
        if(matcher.matches()){
            User user = new User();
            user.setName(matcher.group(1));
            user.setGender(matcher.group(2));
            setValue(user);//赋值
        }
    }
}
public class MyBeanFactoryProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) throws BeansException {
        System.out.println("postProcessBeanFactory");
        factory.registerCustomEditor(User.class,UserEditor.class);

    }
public class Bean1 {
    private  User user;
    private String tag;

    public String getTag() {
        return tag;
    }

    public void setTag(String tag) {
        this.tag = tag;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

}

改造练习1

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean class="org.example.User"></bean>

    <bean id="bean1" class="org.example.Bean1" init-method="toString">
        <property name="user" value="[xixi-boy]"></property>
        <property name="tag" value="春和景明"></property>
    </bean>


    <bean class="org.example.MyBeanFactoryProcessor">
        <property name="editors">
            <map>
                <entry key="org.example.User" value="org.example.UserEditor"></entry>
            </map>
        </property>
    </bean>
    <bean class="org.example.MyBeanPostProcessor"></bean>
</beans>
public class MyBeanFactoryProcessor implements BeanFactoryPostProcessor {
    Map<Class,Class <? extends PropertyEditor>> editors;

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) throws BeansException {
        System.out.println("postProcessBeanFactory");
        for (Map.Entry<Class,Class<? extends PropertyEditor>> entry: editors.entrySet()){
            factory.registerCustomEditor(entry.getKey(),entry.getValue());
        }
    }

    public Map<Class, Class<? extends PropertyEditor>> getEditors() {
        return editors;
    }

    public void setEditors(Map<Class, Class<? extends PropertyEditor>> editors) {
        this.editors = editors;
    }
}

内置容器后置处理器

  • CustomEditorConfigurer 来 实现改造练习1
    <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
        <property name="customEditors">
            <map>
                <entry key="org.example.User" value="org.example.UserEditor"></entry>
            </map>
        </property>
    </bean>
  • PropertyPlaceholderConfigurer 用来读取属性文件,以及常用的类型转换
  • applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean class="org.example.User"></bean>

    <bean id="bean1" class="org.example.Bean1" init-method="toString">
        <property name="user" value="[xixi-boy]"></property>
        <property name="tag" value="${tag}"></property>
    </bean>

    <bean class="org.example.MyBeanPostProcessor"></bean>

    <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
        <property name="customEditors">
            <map>
                <entry key="org.example.User" value="org.example.UserEditor"></entry>
            </map>
        </property>
    </bean>

    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:user.properties"></property>
    </bean>
</beans>

  • user.propperties
tag=Yeah!
posted @ 2020-02-16 21:04  VVII  阅读(384)  评论(0)    收藏  举报