Spring 的 IOC 和 AOP的简单实现

一、IOC

1、配置文件实现IOC

IOC :控制反转,将创建对象的控制权又之前的new转移给Spring框架,目的是为了解耦。

  1. 导入相应的Jar包。
  2. 导入配置文件applicationContext.xml  并进行配置如下:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans" 
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:context="http://www.springframework.org/schema/context" 
    	xmlns:jdbc="http://www.springframework.org/schema/jdbc"  
    	xmlns:jee="http://www.springframework.org/schema/jee" 
    	xmlns:tx="http://www.springframework.org/schema/tx"
    	xmlns:aop="http://www.springframework.org/schema/aop" 
    	xmlns:mvc="http://www.springframework.org/schema/mvc"
    	xmlns:util="http://www.springframework.org/schema/util"
    	xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    	xsi:schemaLocation="
    		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
    		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
    		http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
    		http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
    		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
    		http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
    		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
    		http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
    		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd">
       
    
        <!-- 菜系类 -->
        <bean id="cuisine" class="com.bb.hrb.pojo.Cuisine">
        	<!-- <property name="name" value="鲁菜"></property>-->
        	<constructor-arg index="0" value="东北菜"></constructor-arg>
        </bean>
        <!-- 菜品类 -->
        <bean id="food" class="com.bb.hrb.pojo.Food">
        	<!-- 通过setter方法进行依赖注入,直接引用上面的id为cuisine属性赋值 -->
        	<!-- <property name="cuisine" ref="cuisine"></property>-->
        	<!-- 通过构造器进行依赖注入 -->
        	<constructor-arg index="0" value="猪肉炖粉条"></constructor-arg>
        	<constructor-arg index="1" value="36.8"></constructor-arg>
        	<constructor-arg index="2" ref="cuisine"></constructor-arg>
        </bean>
    
    
    </beans>
    

    属性介绍:

      <bean id="" class=""></bean>
      class属性是用来指明类的包名加类名,id属性用来获取这个bean对象
    
      <bean id="" class="">
        <property name="" ref=""></property>
       </bean>
      property标签用来通过setter方法进行依赖注入,name属性是bean对象中属性名,ref指向一个
        bean的id,还可以有value属性,用于直接设置基本数据类型
    
       <bean id="" class="">
        <constructor-arg index="" value="" ref=""></constructor-arg>
       </bean>
       constructor-arg标签是通过构造器进行依赖注入,index属性指定第几个构造器参数0为第一个,
        value用于直接设置基本数据类型。ref指向一个bean的id
  3. 现在就可以直接使用了!实现如下:

// 读取配置文件,如果配置文件中bean中已经赋值,则返回一个赋好值得对象,反之则返回空对象
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//food为配置文件里的id
Food food = (Food) ac.getBean("food");
System.out.println(food);

2、注解实现IOC

 使用注解只需要在Spring配置文件中添加标签:自动扫描注解
    <context:component-scan base-package="com.bb.hrb"></context:component-scan>

1、bean注解
  @Control 用于控制层组件
  @Service 用于业务层组件
  @Respository 用于DAO层组件
  @Component 用于其它组件
  以上注解使用后都可以创建bean对象,没有区别,不同的使用只是便于分层理解
  添加注解之后默认将类名(首字母小写)定义为bean的id名,id也可以自己定义(注解后
添加小括号双引号,在其中添加自定义的id名)

  2、依赖注入注解
  @Resource JDK提供的
  @AutoWired Spring提供的   默认按照类型匹配,也可指定id
  @Qualifier 配合@AutoWired使用,用于指定注入的bean的id

二、AOP

1、配置文件实现AOP

AOP: "面向切面编程"或者叫做"面向方面编程"
        可以动态的在一个类的方法执行前后自动之前其它类的方法,在不改变这两个类代码的前提下就可以实现,这种编程思想就是"面向切面编程",当不再需要使用时可以自由分开。

1、首先还是导入相应的jar包

2、模拟创建 两个类

扫描二维码关注公众号,回复: 4547997 查看本文章

UserService类

public class UserService{

	public void addUser() {
		System.out.println("用户注册");
	}

	public String deleteUser() {
		System.out.println("删除用户");
        String name = null;
		try{
			name.length();
		} catch(Exception ex) {}
		return "success";
	}

}

UserLogging通知类

import org.aspectj.lang.ProceedingJoinPoint;

public class UserLogging {
	public void logger() {
		System.out.println("前置通知...");
	}
	public void afterLogger() {
		System.out.println("最终通知...");
	}
	public void afterLoggerReturning(Object ret) {
		System.out.println("后置通知..." + ", 返回值是:" + ret);
	}
	public void afterLoggerThrowing(Exception ex) {
		System.out.println("异常通知...");
		//ex.printStackTrace();
	}
	/*
	 * 环绕通知需要ProceedingJoinPoint执行proceed()目标方法
	 * 并且需要return执行proceed()后的返回值
	 */
	public Object aroundLogger(ProceedingJoinPoint pjp) throws Throwable {
		System.out.println("环绕通知前部...");
		Object r = pjp.proceed();// 执行目标方法
		System.out.println("环绕通知后部...");
		return r;
	}
}

3、然后在Spring配置文件中加入

  	<bean id="userService" class="com.oracle.service.UserServiceImpl"></bean>
	
	<bean id="logg" class="com.oracle.aop.UserLogging"></bean>
	
	<aop:config>
		<!-- 定义切入点 -->
        <!-- 第一个*代表返回值,第二个*代表类,第三个*代表方法,(..)所有的重载方法,..表示任意的参数列表 -->
		<aop:pointcut expression="execution(* com.oracle.service.*.*(..))" id="servicePointcut"/>
		<!-- 配置切面 -->
		<aop:aspect id="loggeraspect" ref="logg">
			<!-- 前置通知 -->
			<aop:before method="logger" pointcut-ref="servicePointcut"/>
			<!-- 最终通知 -->
			<aop:after method="afterLogger" pointcut-ref="servicePointcut"/>
			<!-- 后置通知 returning="ret"的值要和异常通知的方法的参数一致 -->
			<aop:after-returning method="afterLoggerReturning" pointcut-ref="servicePointcut" returning="ret"/>
			<!-- 异常通知 throwing="ex"的值要和异常通知的方法的参数一致 -->
			<aop:after-throwing method="afterLoggerThrowing"  pointcut-ref="servicePointcut" throwing="ex"/>
			<!-- 环绕通知 -->
			<aop:around method="aroundLogger" pointcut-ref="servicePointcut"/>
		</aop:aspect>
	</aop:config>

4、大功告成,写一个测试类测试一下吧!

public class TestUserService {
	public static void main(String[] args) {
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		UserService service = (UserService) ac.getBean("userService");
		service.addUser();
		String r = service.deleteUser();
		System.out.println(r);
	}
}

2、注解实现AOP

使用注解只需要在Spring配置文件中写两行

    <!-- 注解IOC -->
    <context:component-scan base-package="com.oracle"></context:component-scan>
    <!-- 注解AOP -->
    <aop:aspectj-autoproxy />

举个栗子:

我们把上面用配置文件实现的改一下

UserService类:

import org.springframework.stereotype.Service;

@Service("userService")
public class UserService {

	public void addUser() {
		System.out.println("用户注册");
	}

	public String deleteUser() {
		System.out.println("删除用户");
		String name = null;
		try{
			name.length();
		} catch(Exception ex) {}
		return "success";
	}

}

UserLogging通知类:这里只拿前置通知为例

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class UserLogging {
	// 定义切入点,这个方法就相当于切入点id
	@Pointcut("execution(* com.oracle.service.*.*(..))")
	public void servicePointcut(){}
	
	@Before("servicePointcut()")
	public void logger() {
		System.out.println("前置通知...");
	}
	public void afterLogger() {
		System.out.println("最终通知...");
	}
	public void afterLoggerReturning(Object ret) {
		System.out.println("后置通知..." + ", 返回值是:" + ret);
	}
	public void afterLoggerThrowing(Exception ex) {
		System.out.println("异常通知...");
		//ex.printStackTrace();
	}
	/*
	 * 环绕通知需要ProceedingJoinPoint执行proceed()目标方法
	 * 并且需要return执行proceed()后的返回值
	 */
	public Object aroundLogger(ProceedingJoinPoint pjp) throws Throwable {
		System.out.println("环绕通知前部...");
		Object r = pjp.proceed();// 执行目标方法
		System.out.println("环绕通知后部...");
		return r;
	}
}

好了可以测试一下了,测试类用上面的就可以。

猜你喜欢

转载自blog.csdn.net/CaesarXin/article/details/84109461