Spring 教程02

spring-2
1.    Xml


<!-- \src\applicationContext-annotation.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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <!-- 配置自动扫描的包 -->
    <context:component-scan base-package="com.atguigu.spring.ref"></context:component-scan>

</beans>

<!-- \src\applicationContext-aop.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:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <!-- 自动扫描的包 -->
    <context:component-scan base-package="com.atguigu.spring.aop"></context:component-scan>

    <!-- 使 AspectJ 的注解起作用 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

</beans>

<!-- \src\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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--  
        1. 默认情况下, IOC 容器中的 bean 是单例的! 若对象是单例的, 则在创建 IOC 容器时即创建 bean 的实例, 并对 bean 的属性进行初始化. 
        2. 可以通过 bean 的 scope 属性来修改 bean 的作用域. 若取值为 prototype, 则 bean 为原型的: 每次向容器获取实例, 得到的都是一个新的对象.
        而且, 不在创建 IOC 容器时创建 bean 的实例了. 
        3. IOC 容器中 bean 的生命周期: 
        3.1 一般地, 讨论 bean 的生命周期, 是建立在 bean 是单例的基础上的. 
        3.2 可以为 bean 指定 init 和 destroy 方法
        3.3 还可以通过 bean 的后置处理器来更加丰富 bean 的生命周期方法(面试时.).
    -->
    <bean id="helloWorld" 
        class="com.atguigu.spring.helloworld.HelloWorld" 
        scope="singleton"
        init-method="init"
        destroy-method="destroy">
        <property name="userName" value="atguigu"></property>
    </bean>
    
    <!--  
        1. 在 IOC 容器中配置 bean 之间的关联关系
    -->
    <bean id="userDao"
        class="com.atguigu.spring.ref.UserDao"></bean>

    <bean id="userService"
        class="com.atguigu.spring.ref.UserService">
        <property name="userDao" ref="userDao"></property>  
    </bean>
    
    <bean id="userAction" 
        class="com.atguigu.spring.ref.UserAction">
        <property name="userService" ref="userService"></property>
    </bean>

</beans>
2.    Java


// \src\com\atguigu\spring\aop\ArithmeticCalculator.java
package com.atguigu.spring.aop;

public interface ArithmeticCalculator {

    int add(int i, int j);
    int sub(int i, int j);
    
    int mul(int i, int j);
    int div(int i, int j);
    
}

// \src\com\atguigu\spring\aop\ArithmeticCalculatorImpl.java
package com.atguigu.spring.aop;

import org.springframework.stereotype.Component;

@Component("arithmeticCalculator")
public class ArithmeticCalculatorImpl implements ArithmeticCalculator {

    @Override
    public int add(int i, int j) {
        int result = i + j;
        return result;
    }

    @Override
    public int sub(int i, int j) {
        int result = i - j;
        return result;
    }

    @Override
    public int mul(int i, int j) {
        int result = i * j;
        return result;
    }

    @Override
    public int div(int i, int j) {
        int result = i / j;
        return result;
    }

}

// \src\com\atguigu\spring\aop\ArithmeticCalculatorLoggingImpl.java
package com.atguigu.spring.aop;

public class ArithmeticCalculatorLoggingImpl implements ArithmeticCalculator {

    @Override
    public int add(int i, int j) {
        System.out.println("The method add begins with [" + i + "," + j + "]");
        int result = i + j;
        System.out.println("The method add ends with " + result);
        return result;
    }

    @Override
    public int sub(int i, int j) {
        System.out.println("The method sub begins with [" + i + "," + j + "]");
        int result = i - j;
        System.out.println("The method sub ends with " + result);
        return result;
    }

    @Override
    public int mul(int i, int j) {
        System.out.println("The method mul begins with [" + i + "," + j + "]");
        int result = i * j;
        System.out.println("The method mul ends with " + result);
        return result;
    }

    @Override
    public int div(int i, int j) {
        System.out.println("The method div begins with [" + i + "," + j + "]");
        int result = i / j;
        System.out.println("The method div ends with " + result);
        return result;
    }

}

// \src\com\atguigu\spring\aop\ArithmeticCalculatorLoggingProxy.java
package com.atguigu.spring.aop;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

public class ArithmeticCalculatorLoggingProxy {
    
    //要代理的对象
    private ArithmeticCalculator target;
    
    public ArithmeticCalculatorLoggingProxy(ArithmeticCalculator target) {
        super();
        this.target = target;
    }

    //返回代理对象
    public ArithmeticCalculator getLoggingProxy(){
        ArithmeticCalculator proxy = null;
        
        ClassLoader loader = target.getClass().getClassLoader();
        Class [] interfaces = new Class[]{ArithmeticCalculator.class};
        InvocationHandler h = new InvocationHandler() {
            /**
             * proxy: 代理对象。 一般不使用该对象
             * method: 正在被调用的方法
             * args: 调用方法传入的参数
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args)
                    throws Throwable {
                String methodName = method.getName();
                //打印日志
                System.out.println("[before] The method " + methodName + " begins with " + Arrays.asList(args));
                
                //调用目标方法
                Object result = null;
                
                try {
                    //前置通知
                    result = method.invoke(target, args);
                    //返回通知, 可以访问到方法的返回值
                } catch (NullPointerException e) {
                    e.printStackTrace();
                    //异常通知, 可以访问到方法出现的异常
                }
                
                //后置通知. 因为方法可以能会出异常, 所以访问不到方法的返回值
                
                //打印日志
                System.out.println("[after] The method ends with " + result);
                
                return result;
            }
        };
        
        /**
         * loader: 代理对象使用的类加载器。 
         * interfaces: 指定代理对象的类型. 即代理代理对象中可以有哪些方法. 
         * h: 当具体调用代理对象的方法时, 应该如何进行响应, 实际上就是调用 InvocationHandler 的 invoke 方法
         */
        proxy = (ArithmeticCalculator) Proxy.newProxyInstance(loader, interfaces, h);
        
        return proxy;
    }
}

// \src\com\atguigu\spring\aop\LoggingAspect.java
package com.atguigu.spring.aop;

import java.util.Arrays;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

/**
 * AOP 的 helloWorld
 * 1. 加入 jar 包
 * com.springsource.net.sf.cglib-2.2.0.jar
 * com.springsource.org.aopalliance-1.0.0.jar
 * com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
 * spring-aspects-4.0.0.RELEASE.jar
 * 
 * 2. 在 Spring 的配置文件中加入 aop 的命名空间。 
 * 
 * 3. 基于注解的方式来使用 AOP
 * 3.1 在配置文件中配置自动扫描的包: <context:component-scan base-package="com.atguigu.spring.aop"></context:component-scan>
 * 3.2 加入使 AspjectJ 注解起作用的配置: <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
 * 为匹配的类自动生成动态代理对象. 
 * 
 * 4. 编写切面类: 
 * 4.1 一个一般的 Java 类
 * 4.2 在其中添加要额外实现的功能. 
 *
 * 5. 配置切面
 * 5.1 切面必须是 IOC 中的 bean: 实际添加了 @Component 注解
 * 5.2 声明是一个切面: 添加 @Aspect
 * 5.3 声明通知: 即额外加入功能对应的方法. 
 * 5.3.1 前置通知: @Before("execution(public int com.atguigu.spring.aop.ArithmeticCalculator.*(int, int))")
 * @Before 表示在目标方法执行之前执行 @Before 标记的方法的方法体. 
 * @Before 里面的是切入点表达式: 
 * 
 * 6. 在通知中访问连接细节: 可以在通知方法中添加 JoinPoint 类型的参数, 从中可以访问到方法的签名和方法的参数. 
 * 
 * 7. @After 表示后置通知: 在方法执行之后执行的代码. 
 */

//通过添加 @Aspect 注解声明一个 bean 是一个切面!
@Aspect
@Component
public class LoggingAspect {

    @Before("execution(public int com.atguigu.spring.aop.ArithmeticCalculator.*(int, int))")
    public void beforeMethod(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        Object [] args = joinPoint.getArgs();
        
        System.out.println("The method " + methodName + " begins with " + Arrays.asList(args));
    }
    
    @After("execution(* com.atguigu.spring.aop.*.*(..))")
    public void afterMethod(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("The method " + methodName + " ends");
    }
    
}

// \src\com\atguigu\spring\aop\Main.java
package com.atguigu.spring.aop;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    
    public static void main(String[] args) {
//      ArithmeticCalculator arithmeticCalculator = new ArithmeticCalculatorImpl();
//      
//      arithmeticCalculator = 
//              new ArithmeticCalculatorLoggingProxy(arithmeticCalculator).getLoggingProxy();
//      
//      int result = arithmeticCalculator.add(11, 12);
//      System.out.println("result:" + result);
//      
//      result = arithmeticCalculator.div(21, 3);
//      System.out.println("result:" + result);
        
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext-aop.xml");
        ArithmeticCalculator arithmeticCalculator = (ArithmeticCalculator) ctx.getBean("arithmeticCalculator");
        
        System.out.println(arithmeticCalculator.getClass().getName());
        
        int result = arithmeticCalculator.add(11, 12);
        System.out.println("result:" + result);
        
        result = arithmeticCalculator.div(21, 3);
        System.out.println("result:" + result);
    }
    
}

// \src\com\atguigu\spring\helloworld\HelloWorld.java
package com.atguigu.spring.helloworld;

public class HelloWorld {
    
    //字段
    private String user;
    
    public HelloWorld() {
        System.out.println("HelloWorld's constructor...");
    }
    
    //JavaBean 使用 setter 和 getter 来定义属性
    public void setUserName(String user) {
        System.out.println("setUserName:" + user);
        this.user = user;
    }
    
    public void hello(){
        System.out.println("Hello:" + user);
    }
    
    public void init(){
        System.out.println("init method...");
    }
    
    public void destroy(){
        System.out.println("destroy method...");
    }
    
}

// \src\com\atguigu\spring\helloworld\Main.java
package com.atguigu.spring.helloworld;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    
    public static void main(String[] args) {
        
        //1. 创建 IOC 容器
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        
        //2. 从 IOC 容器中获取 bean 实例
        HelloWorld helloWorld = (HelloWorld) ctx.getBean("helloWorld");
        
        //3. 调用 bean 的方法
        helloWorld.hello();
        
        HelloWorld helloWorld2 = (HelloWorld) ctx.getBean("helloWorld");
        System.out.println(helloWorld == helloWorld2);
        
        //4. 关闭容器
        ctx.close();
    }
    
}

// \src\com\atguigu\spring\ref\Main.java
package com.atguigu.spring.ref;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    
    public static void main(String[] args) {
        
        //1. 创建 IOC 容器
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext-annotation.xml");
        
        UserAction userAction = (UserAction) ctx.getBean("userAction");
        userAction.execute();
    }
    
}

// \src\com\atguigu\spring\ref\UserAction.java
package com.atguigu.spring.ref;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class UserAction {

    private UserService userService;
    
    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
    
    public void execute(){
        System.out.println("execute...");
        userService.addNew();
    }
    
}

// \src\com\atguigu\spring\ref\UserDao.java
package com.atguigu.spring.ref;

import org.springframework.stereotype.Repository;

@Repository
public class UserDao {

    public void save(){
        System.out.println("UserDao's save...");
    }
    
}

// \src\com\atguigu\spring\ref\UserService.java
package com.atguigu.spring.ref;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Autowired
    private UserDao userDao;
    
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    
    public void addNew(){
        System.out.println("addNew...");
        userDao.save();
    }
    
}

 

posted on 2017-09-03 11:42  程序员修仙之路  阅读(208)  评论(0编辑  收藏  举报