Spring [внедрение зависимостей] так просто

Java Spring

предисловие

Во второй части Spring я в основном объясняю проблему использования контейнера IOC для создания объектов в модуле Spring Core.Используйте контейнер IOC для разрешения зависимостей между объектами!

Просмотрите предыдущие зависимости объекта

Давайте посмотрим на нашу предыдущую историю зависимостей объектов.

прямой новый объект

  • Вначале мы напрямую присваиваем новый объект свойству userDao службы...

class  UserService{
	UserDao userDao = new UserDao();
}

Напишите DaoFactory и используйте строки для поддержки зависимостей

  • Позже мы обнаружили, что уровень сервиса тесно связан с уровнем dao.Мы написали DaoFactory, и на сервисном уровне, пока передается строка, может быть создан соответствующий объект дао-слоя.

  • DaoFactory


public class DaoFactory {

    private static final DaoFactory factory = new DaoFactory();
    private DaoFactory(){}

    public static DaoFactory getInstance(){
        return factory;
    }

    public <T> T createDao(String className,Class<T> clazz){
        try{
            T t = (T) Class.forName(className).newInstance();
            return t;
        }catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}

  • serivce
    private CategoryDao categoryDao = DaoFactory.getInstance().createDao("zhongfucheng.dao.impl.CategoryDAOImpl", CategoryDao.class);

    private BookDao bookDao = DaoFactory.getInstance().createDao("zhongfucheng.dao.impl.BookDaoImpl", BookDao.class);

    private UserDao userDao = DaoFactory.getInstance().createDao("zhongfucheng.dao.impl.UserDaoImpl", UserDao.class);

    private OrderDao orderDao = DaoFactory.getInstance().createDao("zhongfucheng.dao.impl.OrderDaoImpl", OrderDao.class);

DaoFactory читает файлы конфигурации

  • Позже мы обнаружили, чтоЧтобы изменить класс реализации Dao, вам все равно придется изменить исходный код сервисного уровня.Ах..Итак, мы читаем конфигурационный файл о daoImpl в DaoFactory и создаем объекты в соответствии с конфигурационным файлом, чтобы созданный daoImpl был прозрачным для сервисного уровня.

  • DaoFactory



public class DaoFactory {
	
	private  UserDao userdao = null;
	
	private DaoFactory(){
		try{
			InputStream in = DaoFactory.class.getClassLoader().getResourceAsStream("dao.properties");
			Properties prop = new Properties();
			prop.load(in);
			
			String daoClassName = prop.getProperty("userdao");
			userdao = (UserDao)Class.forName(daoClassName).newInstance();
			
		}catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	private static final DaoFactory instance = new DaoFactory();
	
	public static DaoFactory getInstance(){
		return instance;
	}
	
	
	public UserDao createUserDao(){
		return userdao;
	}
	
}

  • service
	UserDao dao = DaoFactory.getInstance().createUserDao();

Внедрение зависимостей Spring

С помощью описанного выше процесса мы можем четко найти:Зависимости между объектами фактически присваивают значения свойствам объектов! Зависимости существуют, потому что у объектов есть переменные других объектов....

Spring предоставляет несколько способов присвоения значений свойствам

  • 1) Через конструктор
  • 2) Вводить значения в свойства через метод set
    1. p пространство имен
  • 4) Автоматическая сборка (разбираюсь)
  • 5) Аннотация

Настройка тестовой среды

  • Переменная userDao используется в UserService для поддержания зависимости от уровня Dao.

  • UserAction использует переменную userService для поддержания зависимостей со слоем службы.

  • userDao

public class UserDao {

	public void save() {
		System.out.println("DB:保存用户");
	}
}

  • userService

public class UserService {
	
	private UserDao userDao; 

	public void save() {
		userDao.save();
	}
}

  • userAnction
public class UserAction {

	private UserService userService;

	public String execute() {
		userService.save();
		return null;
	}
}

Конструктор присваивает значение свойству

По сути, мы объясняемЯ уже говорил о создании конструктора с параметрами... подытожим..

насПросто проверьте зависимости между сервисом и дао....существуетДобавить конструктор в сервис, параметр userDao

    public UserService(UserDao userDao) {
        this.userDao = userDao;
		
		//看看有没有拿到userDao
		System.out.println(userDao);
    }

Файл конфигурации applicationContext.xml


    <!--创建userDao对象-->
    <bean id="userDao" class="UserDao"/>

    <!--创建userService对象-->
    <bean id="userService" class="UserService">
        <!--要想在userService层中能够引用到userDao,就必须先创建userDao对象-->
        <constructor-arg index="0" name="userDao" type="UserDao" ref="userDao"></constructor-arg>
    </bean>

  • Тест: объект userDao может быть успешно получен

        // 创建容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

        //得到service对象
        UserService userService = (UserService) ac.getBean("userService");

这里写图片描述


Внедрение значений в свойства через set-методы

Здесь мы также тестируем зависимости между сервисом и уровнем dao...Внедрить userDao в UserService через метод set на сервисном уровне.

  • Добавить метод set в UserService

public class UserService {

    private UserDao userDao;


    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;

        //看看有没有拿到userDao
        System.out.println(userDao);
    }

    public void save() {
        userDao.save();
    }
}

Файл конфигурации applicationContext.xml: назначение свойств свойствам через узлы свойств

  • Ссылочные типы используют атрибут ref
  • Базовые типы используют атрибут value

    <!--创建userDao对象-->
    <bean id="userDao" class="UserDao"/>

    <!--创建userService对象-->
    <bean id="userService" class="UserService">
        <property name="userDao" ref="userDao"/>
    </bean>

  • контрольная работа:

这里写图片描述


внутренняя фасоль

мы были простоСначала создайте объект userDao, а затем используйте userService для ссылки на объект userDao....у нас другой способ мышления:Сначала создайте userService, обнаружите, что userService нужны атрибуты userDao, а затем создайте userDao....посмотрим, как устроен такой образ мышления:

Файл конфигурации applicationContext.xml: узел свойств, встроенный узел компонента


    <!--
        1.创建userService,看到有userDao这个属性
        2.而userDao这个属性又是一个对象
        3.在property属性下又内置了一个bean
        4.创建userDao
    -->
    <bean id="userService" class="UserService">
        <property name="userDao">
            <bean id="userDao" class="UserDao"/>
        </property>
    </bean>


  • контрольная работа

这里写图片描述

Мы обнаружили, что этот способ мышления совпадает с порядком выполнения доступа к серверу, ноЕсли userDao будет использоваться другими службами несколько раз, его необходимо настроить несколько раз....

значение свойства внедрения пространства имен p

p имя управляет таким образомПо сути, это оптимизация заданного метода, который оптимизирует конфигурацию....p пространство имен этого содержимогоЕго необходимо использовать в версии Spring3 или выше....Давайте посмотрим:

Файл конфигурации applicationContext.xml: используйте пространство имен p


    <bean id="userDao" class="UserDao"/>
    
    <!--不用写property节点了,直接使用p名称空间-->
    <bean id="userService" class="UserService" p:userDao-ref="userDao"/>

  • контрольная работа

这里写图片描述


автоматическая сборка

Spring также предоставляет функцию автоматического подключения, что может значительно упростить нашу настройку.

По умолчанию автозагрузка не включена, обычно используются два типа автосборки:

  • Собрать по имени
  • Собрать по классу типа

Конфигурация XML по имени

Файл конфигурации applicationContext.xml: используйте автопроводку, согласно имени


    <bean id="userDao" class="UserDao"/>

    <!--
        1.通过名字来自动装配
        2.发现userService中有个叫userDao的属性
        3.看看IOC容器中没有叫userDao的对象
        4.如果有,就装配进去
    -->
    <bean id="userService" class="UserService" autowire="byName"/>

  • контрольная работа

这里写图片描述


Конфигурация XML в соответствии с типом

Файл конфигурации applicationContext.xml: используйте автопроводку, в зависимости от типа

Стоит отметить, что:Если использовать автоматическую сборку по типам, в IOC-контейнере может быть только один такой тип, иначе будет выдано сообщение об ошибке!


    <bean id="userDao" class="UserDao"/>

    <!--
        1.通过名字来自动装配
        2.发现userService中有个叫userDao的属性
        3.看看IOC容器UserDao类型的对象
        4.如果有,就装配进去
    -->
    <bean id="userService" class="UserService" autowire="byType"/>

  • контрольная работа:

这里写图片描述


Мы просто тестируем зависимости между двумя объектами, если у нас много объектов, мы также можемИспользовать автоматическое назначение по умолчанию

这里写图片描述


###Автопроводка с использованием аннотаций###

@Autowired аннотация для автопроводки:

  • Можно декорировать на конструкторе
  • Его также можно изменить в методе установки
  • @Inject из java имеет ту же функциональность, что и @AutoWired.

Если нет подходящего bean-компонента, и во избежание исключений мы можем использовать для атрибута required значение false. 【Осторожность】

  • тестовый код
@Component
public class UserService {

    private UserDao userDao ;


    @Autowired
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
}

Успешно получить ссылку на userDao

这里写图片描述

Реализуйте зависимости объектов с помощью класса конфигурации JavaConfig.

Есть два способа (Но я не могу проверить это, если вы можете, дайте мне знать в комментариях.....)

  • Первый тип (не тестировался)

import org.springframework.context.annotation.Bean;

@org.springframework.context.annotation.Configuration
public class Configuration {

    @Bean()
    public UserDao userDao() {

        return new UserDao();
    }

    @Bean
    public UserService userService() {

        //直接调用@bean的方法
        return new UserService(userDao());
    }

}

  • Второй (не могу проверить)

import org.springframework.context.annotation.Bean;

@org.springframework.context.annotation.Configuration
public class Configuration {

    @Bean()
    public UserDao userDao() {

        return new UserDao();
    }

    @Bean
    public UserService userService(UserDao userDao) {

        //通过构造函数依赖注入
        return new UserService(userDao);
    }

}

这里写图片描述


  • Если я прохожу напрямую через конструктор, то сообщается об ошибке

import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.context.annotation.Bean;

@org.springframework.context.annotation.Configuration
public class Configuration {

    @Bean()
    public UserDao userDao() {

        return new UserDao();
    }

    @Bean(autowire = Autowire.BY_TYPE)
    public UserService userService(UserDao userDao) {

        return new UserService(userDao);
    }

}

这里写图片描述


  • Только так я могу получить ссылку на userDao в своем тесте.
public class Configuration {

    @Bean()
    public UserDao userDao() {

        return new UserDao();
    }

    @Bean(autowire = Autowire.BY_TYPE)
    public UserService userService() {

        return new UserService(userDao());
    }

}


这里写图片描述


Конечно,Самый простой и понятный способЕсть еще один:Добавьте метод setUser() в UserService, а затем просто установите его в..

  • UserService

public class UserService {

    private UserDao userDao ;

    public UserService() {
    }

    public UserService(UserDao userDao) {


    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
}
  • Config

import org.springframework.context.annotation.Bean;

@org.springframework.context.annotation.Configuration
public class Config1 {

    @Bean(name = "userDao")
    public UserDao userDao() {

        return new UserDao();
    }


    @Bean(name="userService")
    public UserService userService() {

        UserService userService = new UserService();

        userService.setUserDao(userDao());

        return userService;
    }

}

这里写图片描述


В конце концов

Расширенное чтение:

Если в статье есть какие-либо ошибки, пожалуйста, поправьте меня, и мы сможем общаться друг с другом. Учащиеся, привыкшие читать технические статьи в WeChat и желающие получить больше ресурсов по Java, могутОбратите внимание на публичный аккаунт WeChat: Java3y