据我所知,Spring Framework除了具有单独的上下文之外,没有提供任何封装Spring bean的机制。 因此,当您在Spring的Inversion of Control容器中注册了公共类时,可以通过相同的上下文配置将其自动连接到任何Spring bean中。 这非常强大,但是也很危险。 开发人员可以轻松地将bean耦合在一起。 缺乏纪律的团队可以轻松地开枪射击自己。 不幸的是,我当时正在一个整体项目中,团队用冲锋枪射击自己。 接线经常违反分层规则。 没有人可以轻易遵循依赖于什么的内容。 Bean依赖图太疯狂了。 这在更大的应用中是一个严重的问题。
幸运的是,有一种简单的方法可以封装Spring bean。 Spring可以在类级别使用默认访问修饰符很好地工作。 因此,您可以创建程序包专用bean,该程序包只能在当前程序包中使用。 简单而强大。 让我们看一个例子:
package net.lkrnac.blog.spring.encapsulatebean.service;
import org.springframework.stereotype.Service;
@Service
class AddressService {
public String getAddress(String userName){
return "3 Dark Corner";
}
}
这个简单的bean被连接到同一包中的另一个bean中:
package net.lkrnac.blog.spring.encapsulatebean.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
private AddressService addressService;
@Autowired
public UserService(AddressService addressService) {
this.addressService = addressService;
}
public String getUserDetails(String userName){
String address = addressService.getAddress(userName);
return String.format("User: %s, %s", userName, address);
}
}
主要上下文仅扫描两个bean:
package net.lkrnac.blog.spring.encapsulatebean;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application {
}
这是测试证明它运作良好:
package net.lkrnac.blog.spring.encapsulatebean;
import net.lkrnac.blog.spring.encapsulatebean.service.UserService;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
public class ApplicationTests {
@Autowired
private UserService userService;
@Test
public void isPackagePrivateBeanCalled(){
//GIVEN - spring context defined by Application class
//WHEN
String actualUserDetails = userService.getUserDetails("john");
//THEN
Assert.assertEquals("User: john, 3 Dark Corner", actualUserDetails);
}
}
我相信每个人都应该考虑对每个新bean使用默认的访问修饰符。 显然,每个软件包中都需要一些公共bean。 但是并不是每个豆子都有。 源代码在GitHub上 。
翻译自: https://www.javacodegeeks.com/2014/12/how-to-encapsulate-spring-bean.html