JAVA之旅-简化java开发
为了降低java开发的复杂性,spring采取了以下4种关键策略
- 基于POJO的轻量级和最小侵入行编程
为使不让应用与框架绑死,一个bean不会实现,继承或者导入Spring API相关的任何东西,只是一个普通的java对象。
2. 通过依赖注入和面相接口实现松耦合
每个对象负责管理与自己相互协作的对象(即它所依赖对象)的引用,这将会导致高度耦合和难以测试的代码。
高度耦合的意思是一个类要管理自己的对象,
public class PerformShow implements Perform{ private Star star; public PerformShow() { this.star = new SuperStar(); } }
这是典型的例子,这会使
-
- 内部对象实例可更改性很差,而且功能过于单一。
- 单元测试可很难做,究其原因是无法方便的取出内部对象star.
改造方法是利用依赖注入实现松耦合。分为构造器注入和setter注入两种。
public class PerformShow implements Perform{ private Star star; //constructor public PerformShow(Star star) { this.star = star; } //for setter property public void setStar(Star star) { this.star = star; } }
通过注入,其实就是下面这个样子,但是这里面有几个需要注意的。
-
- 这个单元测试就很好做了,因为我们有有了start这个对象了。
- 类内部的对象和执行方法多变,以前只能限制成SuperStar这个类。现在什么明星只要实现Star接口的都可以。这个也是松耦合的意思,就是以接口实现传递,降低耦合关系。
- 其实基于xml和注解的注入方式都和这个类似,就是方式不一样罢了。
Star star = new SuperStar(); Perform perform = new PerformShow(star);
DI:对象的依赖关系将由负责协调系统中各个对象的第三方组件在创建时设定。对象无需自行创建或管理它们的依赖关系。
用xml的写法如下。
<bean id="performconstructor" class="spring.in.action.bean.beanInjectionInitDestroy.PerformShow"> <!--构造器注入,简单值用value,对象用再声明一个bean,ref--> <constructor-arg ref="star"/> </bean> <bean id="star" class="spring.in.action.bean.beanInjectionInitDestroy.SuperStar"> <property name="name" value="刘德华"/> </bean>
利用上下文把其加载进来,这样就做到perform接口不知实现类是谁,也不知其内部的star接口是怎样的明星,实现松耦合。
ApplicationContext context = new ClassPathXmlApplicationContext("spring-injection-init-destroy.xml"); Perform performconstructor = (Perform)context.getBean("performconstructor");
3. 基于切面和惯例进行声明式编程(aop)
依赖注入让相互协作的软件组件保持松散耦合,而aop变成允许把遍布应用各处的功能分离出来形成可重用的组件。
诸如日志、事务管理和安全此类的系统服务经常融入到自身核心业务逻辑的组件中去,这些系统服务通常是横切关注点,它们不属于任何一个业务组件,这是就需要aop编程。
这样可以是组件更加关心自身的业务和有很高的内聚性。
public class FamilyCui implements Family { private Member member; public FamilyCui(Member member) { this.member = member; } public void doSomething (){ member.doJob(); } } public class FamilyLog { public void beforFun(){ System.out.println("想知道孩子们在干啥!"); } public void afterFun() { System.out.println("哦,我知道了"); } }
<!--family的bean--> <bean id="family" class="spring.in.action.diAopSimple.di.FamilyCui"> <constructor-arg ref="member" /> </bean> <bean id="member" class="spring.in.action.diAopSimple.di.MemberSon"></bean> <!--aop aspect要用到的类--> <bean id="familyLog" class="spring.in.action.diAopSimple.aop.FamilyLog"></bean> <!--aop的配置--> <aop:config> <!--用familyLog做aop--> <aop:aspect ref="familyLog"> <!--定义切入点--> <aop:pointcut id="doSomthing" expression="execution(* *.doSomething(..))"/> <!--关联切入点,并指定方法--> <aop:before pointcut-ref="doSomthing" method="beforFun"/> <aop:after pointcut-ref="doSomthing" method="afterFun"/> </aop:aspect> </aop:config>
首先我们有一个Family类,我们要把他的方法作为切入点,那我们就需要一个类FamilyLog,然后定义我们的切片方法beforeFun和afterFun,并声明在切入点的什么时候用。
4. 通过切面和模版减少样板式代码
这个很好理解,以JDBC为例,在实质的代码前要有好多的开启关闭动作,用spring可以搞定这些。