Spring框架回顾

       Spring最主要的特点有两个:IOC和AOP,这也是为了解决经常碰到的问题:

              1)对象太多如何管理

              2)共同逻辑和业务逻辑纠缠在一起,错综复杂,如何解耦。

 

 IOC

       IOC的全称是Inversion of Control,中文称为控制反转, Martin Flower由根据它创造了一个新词:Dependency Injection,中文称为依赖注入。这两个词讲的是一回事儿。

  IOC的实质是如何管理对象,传统意义上我们使用new方式来创建对象,但在企业应用开发的过程中,大量的对象创建都在程序中维护很容易造成资源浪费,并且不利于程序的扩展。

  实现IoC通常有三种方式:

        1)利用接口或者继承,一般以接口较多。这种实现方式和我们平时提到的lazy load有异曲同工之妙。

        2)构造函数注入。

        3)属性注入(例如 setter 方法)。

eg:我们先定义两个对象

public class Person {

	private String name;
	private Phone phone; //person依赖于phone
	
	public  Person(){
		System.out.println("我是Person()");
	}
	
	public Phone getPhone() {
		return phone;
	}

	public void setPhone(Phone phone) {
		this.phone = phone;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void call(){
		phone.say();
	}
}


public class Phone {

	public Phone(){
		System.out.println("我是Phone()");
	}
	
	public void say() {
		System.out.println("你好...");
	}

}

接着在spring.xml中声明bean:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

   <bean id="person" class="com.yc.spring.Person">
      <property name="name" value="小明"/> 
      <property name="phone" ref="phone"/>  
   </bean>
   <bean id="phone" class="com.yc.spring.Phone">
   
   </bean>
</beans>

测试文件如下:

public class PersonTest extends TestCase {

	@Test
	public void testPerson() {
		//创建spring容器对象
		ApplicationContext sc=new ClassPathXmlApplicationContext("spring.xml");
		Person person=(Person) sc.getBean("person");
		
		System.out.println(person.getName());
		person.call();                                                                                                                    
	}

}

测试结果如下:

我是Person()
我是Phone()
小明
你好...

  对象的生命周期

  我们可以通过设置bean节点的scope属性来控制对象的声明周期,它包含两个可选值:

         1)singleton,表明系统中对于同一个对象,只保留一个实例。

         2)prototype,表明系统中每次获取bean时,都新建一个对象。

<bean id="userDaoImpl" class = "xxx.xxx.UserDaoImpl" scope="singleton"/>
<bean id="userDaoImpl2" class = "xxx.xxx.UserDaoImpl" scope="prototype"/>

      我们也可以通过使用Annotation来定位Bean,这里就不详细介绍了

      在使用Annotation定位Bean的基础上,我们就可以自动加载对象定义:

<context:component-scan base-package="com.yc.spring"/>

 

AOP

        面向方面的编程,即 AOP,是一种编程技术,它允许程序员对横切关注点或横切典型的职责分界线的行为(例如日志和事务管理)进行模块化。AOP 的核心构造是方面,它将那些影响多个类的行为封装到可重用的模块中。

       AOP 和 IOC 是补充性的技术,它们都运用模块化方式解决企业应用程序开发中的复杂问题。在典型的面向对象开发方式中,可能要将日志记录语句放在所有方法和 Java 类中才能实现日志功能。在 AOP 方式中,可以反过来将日志服务模块化,并以声明的方式将它们应用到需要日志的组件上。当然,优势就是 Java 类不需要知道日志服务的存在,也不需要考虑相关的代码。所以,用 Spring AOP 编写的应用程序代码是松散耦合的。

eg:以下实现一个用于计算的类

public interface ICalculatorLogging {

	public int add(int i, int j);
	
	public int divid(int i, int j);

}

@Component("iCalculatorLogging")
public class CalculatorLoggingImpl implements ICalculatorLogging {

	@Override
	public int add(int num1, int num2) {
		int result=num1+num2;
		return result;
	}

	@Override
	public int divid(int num1, int num2) {
		int result=num1-num2;
		return result;
	}
}

实现一个日志类:

public class LoggingAspect {

	public void before(String Methodname,Object...args){
		LogManager.getLogger().debug(String.format("开始执行%s方法,传入参数为:%s",Methodname,Arrays.toString(args)));
	}
	
	public void afterReturning(String Methodname,Object...args){
		LogManager.getLogger().debug(String.format("执行%s方法成功,运算结果:%s",Methodname,Arrays.toString(args)));
	}
}

接着实现一个日志代理类:

public class CommonProxy<T> {

	private T target;
	
	public T getProxyInstance(T t){
		target = t;
		ClassLoader loader=Thread.currentThread().getContextClassLoader();
		Class<?>[] interfaces=target.getClass().getInterfaces();
		InvocationHandler h=new InvocationHandler(){

			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				String methodName=method.getName();//取到代理方法的方法名
				LoggingAspect loggingAspect=new LoggingAspect();
				loggingAspect.before(methodName, args);
				Object result=method.invoke(target, args);
				loggingAspect.afterReturning(methodName, result);
				return result;
			}
		};
		return (T) Proxy.newProxyInstance(loader, interfaces, h);
	}
}

测试:

public class CalculatorLoggingImplTest {
	
	@Test
	public void testadd01() {
		ICalculatorLogging iCalculator=new CalculatorLoggingImpl();//执行目录
		iCalculator=new CommonProxy<ICalculatorLogging>().getProxyInstance(iCalculator);//在执行过程中添加日志的代理
		int result=iCalculator.add(1,2);
	}
}

输出结果如下:

2018-08-28 20:47:33,699 DEBUG LoggingAspect (LoggingAspect.java:10) - 开始执行add方法,传入参数为:[1, 2]
2018-08-28 20:47:33,716 DEBUG LoggingAspect (LoggingAspect.java:14) - 执行add方法成功,运算结果:[3]

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值