据我所知,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;@Autowiredpublic 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 {@Autowiredprivate UserService userService;@Testpublic void isPackagePrivateBeanCalled(){//GIVEN - spring context defined by Application class//WHENString actualUserDetails = userService.getUserDetails("john");//THENAssert.assertEquals("User: john, 3 Dark Corner", actualUserDetails);}
}
我相信每个人都应该考虑对每个新bean使用默认的访问修饰符。 显然,每个软件包中都需要一些公共bean。 但是并不是每个豆子都有。 源代码在GitHub上 。
翻译自: https://www.javacodegeeks.com/2014/12/how-to-encapsulate-spring-bean.html