Hibernate之后就迎来了Spring, ^_^ ^_^ 不过此处据说是让人看不到春天的。
Spring框架的特点:
1、 黏合剂: 面向组件开发的技术, Spring提供了对已有的各种组件技术的融合。
2、 轻量级的框架: 指应用程序基于框架开发依赖于API的严重程度低(这样子学习成本低 且 便于框架更换)。
都说学习Spring没什么新东西, 主要的就是学习一些思想。 因此今天我便开始学习了IOC思想。
IOC降低了面向对象编程对象之间的耦合度, 学习IOC主要要注意两个方面的问题:
a、 控制什么: 对象之间的依赖关系是什么
b、 反转到哪里
————IOC容器主要做了两项工作:
a、 创建对象
b、 根据对象之间的依赖关系进行注入——使用属性的get()/set()方法 或者使用构造函数。
重点是applicationContext.xml文件的配置, 多练习....
Spring & AOP ——————面向切面编程
切面: 和业务逻辑的核心实现没有关系, 但业务逻辑的实现需要某个领域提供相应的服务(如炒菜与洗菜,刷锅)。
在学习AOP时重点提到了代理模式: 代理模式的用途在于为真正的对象提供一个服务。
代理模式又分为静态代理与动态代理, 静态代理只为某一种对象提供服务, 而动态代理可以为不同类型接口类型的对象提供服务。
代理模式中存在三种角色, 分别是 真实对象、 代理对象、 一个真实对象和代理对象的接口
——————————————如下贴出我写的AOP练习 (以 洗菜——炒菜——洗碗 为例)
A、 不使用代理模式:
public class Worker {
public void beforeWork()
{
System.out.println("炒菜准备工作");
}
public void doWork()
{
beforeWork();
System.out.println("正在炒菜.....");
afterWork();
}
public void afterWork()
{
System.out.println("洗碗工作");
}
}
不使用代理模式有一个很大的弊端就是每次炒菜时都得重复地调用beforeWork()与afterWork()方法, 这样子造成了代码冗余
B、 使用静态代理模式:
CookInterface.java ——真实对象与代理对象的共同接口
public interface CookInterface {
public void doCooking();
}
CookImpl.java ——真实对象, 实现炒菜这个核心业务
public class CookImpl implements CookInterface{
public void doCooking() {
System.out.println("正在炒菜....");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
CookProxy.java ——代理对象
public class CookProxy implements CookInterface{ //代理对象与真实对象实现同一个接口
CookInterface cooker;
public CookInterface getCooker() {
return cooker;
}
public void setCooker(CookInterface cooker) {
this.cooker = cooker;
}
public void doCooking() {
beforeWork();
cooker.doCooking();
afterWork();
}
/**
* 将为核心业务服务的方法抽取到代理对象中
*
*/
public void beforeWork(){
System.out.println("洗菜");
}
public void afterWork(){
System.out.println("洗碗");
}
}
TestAop.java ——测试类
public class TestAop {
public static void main(String[] args) {
CookInterface cooker = new CookImpl();
CookProxy cookerProxy = new CookProxy();
cookerProxy.setCooker(cooker);
cookerProxy.doCooking();
}
}
静态代理模式虽然减少了代码冗余, 但是其只能为实现某一种类型接口的特定对象提供服务
C、 动态代理: (动态代理类与测试类发生了变化, 其他两个类同上)
CookDynamicProxy.java ——动态代理类
/**
* 为不同接口类型的对象动态产生代理对象
* @author Administrator
*
*/
public class CookDynamicProxy implements InvocationHandler{
private Object targetObject; //真实对象
/**
* 动态产生代理对象
*/
public Object createProxyObject(Object targetObject){
this.targetObject = targetObject;
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(), this);
}
/**
* 提供代理的服务(切面)
* proxy是代理对象
* method是代理对象调用的方法
* args是调用方法的实参列别
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
beforeWork();
//调用真实对象的方法
Object result = method.invoke(targetObject, args);
afterWork();
return result;
}
public void beforeWork(){
System.out.println("洗菜");
}
public void afterWork(){
System.out.println("洗碗");
}
}
TestDynamicProxy.java
public class TestDynamicProxy {
public static void main(String[] args) {
CookInterface cooker = new CookImpl();
CookInterface cookerProxy = (CookInterface)new CookDynamicProxy().createProxyObject(cooker);
cookerProxy.doCooking();
}
}
这样子就与具体的接口解耦了。 ^_^ ^_^ 这是一种比较好的做法。
D、 在Spring中使用动态代理模式, 通过配置appicationContext.xml以及调用Spring API的方式实现
这种方式主要是配置applicationContext.xml, 如下是我的配置:
<!-- 配置真实对象 -->
<bean id="realWorker" class="cn.com.aop.CookImpl"></bean>
<!-- 配置通知 -->
<bean id="arroundNote" class="cn.com.aop.ArroundLog"></bean>
<!-- 配置动态代理 -->
<bean id="workProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 指定要实现的接口 -->
<property name="interfaces"><value>cn.com.aop.CookInterface</value></property>
<!-- 指定代理的真实对象 -->
<property name="target" ref="realWorker"></property>
<!-- 指定运行时织入的通知 -->
<property name="interceptorNames">
<list>
<value>arroundNote</value>
</list>
</property>
</bean>
关于源文件只有如下两个与上面的源文件不同, 列举如下:
ArroungLog.java ——通知
/**
* 切面代码,在方法的前后进行织入
* @author Administrator
*
*/
public class ArroundLog implements MethodInterceptor {
public Object invoke(MethodInvocation arg0) throws Throwable {
beforeWork();
Object result = arg0.proceed();
afterWork();
return result;
}
public void beforeWork(){
System.out.println("洗菜");
}
public void afterWork(){
System.out.println("洗碗");
}
}
Test.java ——测试类
public class Test {
public static void main(String[] args) {
Resource resource = new ClassPathResource("applicationContext.xml");
BeanFactory bf = new XmlBeanFactory(resource);
CookInterface cooker = (CookInterface)bf.getBean("workProxy");
cooker.doCooking();
}
}