传统使用新类注入的方式造成代码的耦合,例如:
StudentAction类,依赖StudentBiz,并调用服务层StudentBiz中的getName()方法
public student StudentAction{
StudentBiz studentBiz=new StudentBiz();
public vooid printSTUDENTnAME(){
System.out.println("学生:"+studentBiz.getName())
}
}
服务层StudentBiz又通过新实例化StudnetDao,依赖studnetDao,并调用了studnetDao的的getName()方法。
这样类与类之间层层的依赖会造成,当修改一个类时,其相关依赖的类都要重新编译才能使用,可谓是牵一发而动全身,付出的代价太大,故弹簧推出了依赖注入的解决方案。
1.工厂模式:(使用工厂模式创建对象)
公共界面IStudentBiz {}
公共类StudentBiz实施IStudentBiz {}
public class StudentBizFactory {public static IStudentBiz getInstance(){return new StudentBiz();}}
公共类StudentAction {IStudnetBiz studnetBiz = studnetFactory.getInstance()}
此时,服务类studentBiz发生变化,只需调整studengFactory代码,studentAction不用动。
2.spring的控制反转(IOC)或依赖注入(DI)
弹簧可以管理很多类(java的不就是类与类之间的运作吗,需要预先声明豆,即在的application.xml中配置豆,类之间的依赖关系,如:甲依赖B,则在甲类中需要定义对乙类赋值的设置器方法,这是弹簧对管理类的唯一的要求)举例如下:
public interface IstudentDao {public String getName()}
公共类StudnetDao实现IstudentDao {@override public String getName(返回''李四“//实际中李四是从数据库中取出来//studentDao.getName())}
//业务层
公共接口IStudnetBiz {public String getName()}
公共类StudnetBiz实现IStudentBiz {IStudentDao studntDao; @Override public String getName(){return studnetDao.getName();}}
//与studnetDao.getName()对应的设置器方法是:
public void setStudnetDao(IStudnetDao studentDao){this.studentDao = studentDao}
网络层的二传手:
公共课StudentAction {IstudentBiz studentBiz; public void setStudnetDao(IStudnetDao studentDao){this.studentDao = studentDao} public void printName(System.out.println(studentBiz.getName())}
春天中的配置:
<bean id =“studentDao”class =“xxx.xxx.impl.StudentDao”/>
// ID是豆的标记
<bean id =“studentBiz”class =“xxx.xxx.impl.StudentBiz”>
//调用setStudentDao(),为studentBiz的studentDao属性赋值
<property name =“”studentDao>
<ref bean =“studentDao”/>
</属性>
//属性是子标记,定义了对应类的设置器方法
// REF是子标记,定义了需要传递给设置器方法的实例对象
主要方法测试:
ApplicationContext ctx = new ClassPathXmlApplicationContext(xx / xx / application.xml)
StudentAction studentAction =(StudentAction)ctx.getBean(“studentAction”);
studentAction.printName();
依赖注入到此结束。
下面是代理模式:
被代理类:学生(或客户,明星比如刘德华)
代理类:studentProxy(律师,代理人,经纪人)
二者必须都要实现同一个接口Istudent
公共接口Istudent {public void writework()}
公共课学生实施Istudent {@Override public vioid writehomework(println(“我是被代理类,我在写作业”))}
注意,传参是传被代理的接口。
公共课StudentProxy实施Istudent {私人Istudent学生; public StudentProxy(Isudent student){this.student = student} @Override public vioid writehomework {(println(“执行前的日志打印”),student.write.wroteHomwork();, println(“执行后的日志打印”) },
测试代码:
Istudent studnet = new Studnet();
student.writeHomework();
Istudent studentProxy =新的Studnet StudnetProxy(studnet);
studnetProxy.writeHomework();
总结:
最后做事情的是代理类,代理类按照被代理类的意愿做了事情,并打印了日志,它在不修改被代理类的前提下对他加入了日志功能,而且日志完全由代理类进行控制,做到了日志功能和也业务功能的分离,还需增加功能时,按同样的方式创建代理类即可。
AOP是使用代理模式来实现的。aop描述的就是代理模式,它是吧原本的功能方法进行切割,然后把通用的行为插入到切割的位置
如图:在业务功能不变的情况下相应的位置插入了附加的行为(安全框架,事务框架,权限框架,健康系统都是基于AOP的编程实现的)