Spring初体验

本文深入探讨Spring框架特点,包括作为黏合剂的作用和轻量级特性,并着重讲解了面向切面编程(AOP)的概念。通过实例展示了如何利用代理模式和Spring中的动态代理实现AOP,以及在Spring中配置动态代理的步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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();


}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值