Spring DI - różnica @Autowired zmienna a setter

0

Hejka!
Przerabiam sobie kurs na Pluralsight.
Mam przykładowy kod

@Repository("customerRepository")
public class HibernateCustomerRepositoryImpl implements CustomerRepository {

    @Override
    public List<Customer> findAll() {
        List<Customer> customers = new ArrayList<>();

        Customer customer = new Customer();
        customer.setFirstName("Bryan");
        customer.setLastName("Hansen");

        customers.add(customer);
        return customers;
    }
}

i coś takiego:

package com.pluralsight.service;

import com.pluralsight.model.Customer;
import com.pluralsight.repository.CustomerRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service("customerService")
public class CustomerServiceImpl implements CustomerService {

    @Autowired
    private CustomerRepository customerRepository;

    @Override
    public List<Customer> findAll() {
        return customerRepository.findAll();
    }
}

Konfiguracja w xml to:

<context:annotation-config/>
<context:component-scan base-package="com.pluralsight" />

Jaka jest różnica między wstrzykiwaniem tak jak wyżej a wstrzykiwaniem przez setter (kod poniżej)?
Kiedy chcę skorzystać z settera?

package com.pluralsight.service;

import com.pluralsight.model.Customer;
import com.pluralsight.repository.CustomerRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service("customerService")
public class CustomerServiceImpl implements CustomerService {

    //@Autowired
    private CustomerRepository customerRepository;

    @Override
    public List<Customer> findAll() {
        return customerRepository.findAll();
    }

    @Autowired
    public void setCustomerRepository(CustomerRepository customerRepository) {
        System.out.println("We are using setter injection");
        this.customerRepository = customerRepository;
    }
}
0

No jedyna różnica jest taka że jedno wstrzyknięcie jest przez setter a drugie przez konstruktor :D Ja staram się wstrzykywać przez konstruktor i robić pola prywatne, za setterami średnio przepadam w przypadku prawdziwych obiektów a nie pojemniczków na dane :P


@Service("customerService")
public class CustomerServiceImpl implements CustomerService {
 
    @Autowired
    private CustomerRepository customerRepository;
 
    @Override
    public List<Customer> findAll() {
        return customerRepository.findAll();
    }
}

A takie coś daje mi raka (metoda serwisowa która wykonuje jedną metodę na repository)

0

@scibi92: Dzięki za odpowiedź, ale w takim razie mam jeszcze jedno pytanie.
Według autora kursu wstrzykiwanie przez konstruktor wygląda tak:

package com.pluralsight.service;

import com.pluralsight.model.Customer;
import com.pluralsight.repository.CustomerRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service("customerService")
public class CustomerServiceImpl implements CustomerService {

    //@Autowired
    private CustomerRepository customerRepository;

    @Autowired
    public CustomerServiceImpl(CustomerRepository customerRepository) {
        System.out.println("We're using constructor injection");
        this.customerRepository = customerRepository;
    }


    @Override
    public List<Customer> findAll() {
        return customerRepository.findAll();
    }

    //@Autowired
    public void setCustomerRepository(CustomerRepository customerRepository) {
        System.out.println("We are using setter injection");
        this.customerRepository = customerRepository;
    }
}

więc czym jest pierwszy przykład? Również wstrzykiwanie przez konstruktor?

A takie coś daje mi raka (metoda serwisowa która wykonuje jedną metodę na repository)

To tylko przykład :P

1

1 to pole, 2 to przez setter, a 3 to przez konstruktor. 1 przypadek to już w ogóle ciężka onkologia bo uzależnia w pełni kod od frameworka zwłaszcza jak użyjesz tylko

@Autowired

Dodatkowo utrudnia testosowanie, gdy na przykład masz wstrzyknięce przez konstruktor możesz łatwo wstrzyknąc w teście jednostkowym jakiś zmokowany obiekt :)

0

Czyli generalnie wstrzykiwanie:

  • przez pole jest fuj
  • przez setter kiedy mamy głównie dane (np. klasa Address w klasie Person?)
  • przez konstruktor jest ok

Dobrze rozumiem?

1

Tak, settery używam do modeli danych takich jak encje, DTO etc. a do prawdziwych obiektów takich jak na przykład obiekty z logiką bizensową, czy obiekty DAO korzystam z konstruktorów :)

3

Czy przez konstruktor czy przez setter? Temat rzeka. Najlepiej zacząć od opinii guru:

Martin Fowler, Constructor versus Setter Injection. Konkluzja jest taka:

Despite the disadvantages my preference is to start with constructor injection, but be ready to switch to setter injection as soon as the problems I've outlined above start to become a problem.

Czyli zaczynamy od wersji konstruktorowej.

0

Konstruktor bo trudniej o pomyłkę w sensie takim , że setter zwyczajnie łatwiej pominąć niż argument w konstruktorze. Poza tym od springa 4.3 można się obejść bez autołaired.

It is no longer necessary to specify the @Autowired annotation if the target bean only defines one constructor.

1 użytkowników online, w tym zalogowanych: 0, gości: 1