Spring注入&AOP


欢迎大家访问我的网站:www.ifueen.com

Spring注入&AOP

注入

Maven里面注入Spring

创建最基本的Maven项目,进行依赖注入:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.ifueen</groupId>
    <artifactId>spring-day02</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <!--Spring的核心包-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.2.5.RELEASE</version>
        </dependency>
        <!--Context包-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.2.5.RELEASE</version>
        </dependency>
        <!--aop的包-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>4.2.5.RELEASE</version>
        </dependency>
        <!--切面的一个包(织入)-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.8</version>
        </dependency>

        <!-- Spring的测试包 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>4.2.5.RELEASE</version>
            <!--scope:范围,只能在test包中使用-->
            <!--<scope>test</scope>-->
        </dependency>
        <!--junit的测试支持-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.6.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
            <resource>
                <directory>src/test/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
    </build>

</project>

通过构造方法注入参数

<?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="mybean" class="com.ifueen._02constructor.MyBean">

        <!-- 通过索引配置-->
        <!--<constructor-arg index="0" value="罗素"/>
        <constructor-arg index="1" value="3"/>-->

        <!-- 通过name配置 -->
        <!--<constructor-arg name="age" value="30"/>
        <constructor-arg name="name" value="爱伦坡"/>-->

        <!-- 通过类型进行配置-->
        <!--<constructor-arg type="java.lang.String" value="狄更斯"/>
        <constructor-arg type="java.lang.Integer" value="45"/>-->

        <!-- 直接根据参数顺序进行配置,注意!参数顺序一定要相对应-->
        <constructor-arg value="萨特"/>
        <constructor-arg value="30"/>
    </bean>
</beans>

集合&数组&其他属性的注入

<?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="otherBean" class="com.ifueen._03rest.OtherBean"/>
    <bean id="mybean" class="com.ifueen._03rest.MyBean">

    <!-- 一般简单的属性 -->
        
        <property name="id" value="1"/>
        <property name="name" value="山泥若"/>
        <property name="sex" value="true"/>
        <property name="salary" value="797979"/>

    <!-- 数组 -->
        <property name="arrays">
            <array>
                <value>爱伦坡</value>
                <value>伏尔泰</value>
                <value>罗素</value>
            </array>
        </property>

    <!-- List集合 -->
        <property name="list">
            <list>
                <value>娄烨</value>
                <value>王家卫</value>
                <value>李安</value>
            </list>
        </property>

    <!-- set集合 -->
        <property name="set">
            <set>
                <value>诺兰</value>
                <value>昆汀</value>
                <value>斯皮尔伯格</value>
            </set>
        </property>

        <!-- List集合OtherBean-->
        <property name="otherBeanList">
            <list>
                <!-- 内部Bean -->
                <bean class="com.ifueen._03rest.OtherBean"/>
                <bean class="com.ifueen._03rest.OtherBean"/>
                <!-- 外部引用 -->
                <ref bean="otherBean"/>
                <ref bean="otherBean"/>
            </list>
        </property>

        <!-- Set集合OtherBean-->
        <property name="otherBeanSet">
            <list>
                <!-- 内部Bean -->
                <bean class="com.ifueen._03rest.OtherBean"/>
                <bean class="com.ifueen._03rest.OtherBean"/>
                <!-- 外部引用 -->
                <ref bean="otherBean"/>
                <ref bean="otherBean"/>
            </list>
        </property>

        <!-- 简写方式 -->
        <property name="props1">
            <value>
            drivenClassName=com.mysql.jdbc.Driver
            url=jdbc:mysql:///jpa
            username=root
            password=123456
            </value>
        </property>

        <!-- 标准写法 -->
        <property name="props2">
            <props>
            <prop key="drivenClassName">com.mysql.jdbc.Driver</prop>
            <prop key="url">jdbc:mysql:///hello</prop>
            <prop key="username">root</prop>
            <prop key="password">123456</prop>
            </props>
        </property>

        <!-- Map集合 -->
        <property name="hashMap">
        <map>
            <entry key="电影" value="2001太空漫步"/>
            <entry key="导演" value="库布里克"/>
        </map>
        </property>
    </bean>


</beans>

使用全注解

使用全注解的方式和之前SpringMVC的使用方式一模一样

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="com.ifueen._04auto"/>
</beans>

只需要将扫描包路径配置好,然后写三层架构即可

AOP(面向切面编程)

概述

定义:面向切面编程(面向方面编程)

咱们的编程语言从原始机器语言 到过程语言 再到面向对象,从始至终的目的就是为了让代码再加灵活,再加容易让人理解,构建代码更加简单。

AOP的使用只存在于一些特定的场合(具有横切逻辑的应用场合),横切逻辑这个解释可能比较抽象,咱们说得再具体一点,AOP可以用于事务管理,日志管理,性能监测等地方

面试题:Spring是如何实现AOP?

Spring是使用代理模式来实现AOP的

代理模式分两种:静态代理和动态代理

静态代理太过笨重,一般不太使用

动态代理

Spring提供了两种方案:JDK和CGLTB

如果目标对象使用了接口就让JDK来进行代理

如果目标对象没有使用接口就让CGLTB来进行代理

使用XML配置实现AOP

首先定义自定义的事务类(伪事务类)

package com.ifueen._05xmlaop;

import org.aspectj.lang.ProceedingJoinPoint;

/**
 * 自己准备的一个事务
 */
public class TxManager {

    public void begin(){
        System.out.println("开启事务");
    }
    public void commit(){
        System.out.println("提交事务");
    }
    public void rollback(Throwable e){
        System.out.println("回滚事务,异常的原因为"+e.getMessage());
    }
    public void close(){
        System.out.println("关闭资源");
    }

    public void around(ProceedingJoinPoint point){
        /*System.out.println(point.getArgs()); //参数
        System.out.println(point.getSignature()); //获取方法的签名
        System.out.println(point.getTarget().getClass());//真实目标对象
        System.out.println(point.getThis().getClass()); //代理对象*/
        try {
            //开启事务
            begin();
            //这里执行我们自己的代码
            point.proceed();
            //提交事务
            commit();
        } catch (Throwable throwable) {
            //回滚
            rollback(throwable);
            throwable.printStackTrace();
        }finally {
            //关闭
            close();
        }
    }


}

然后进行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"
       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.xsd">
    <bean id="myBeanService" class="com.ifueen._05xmlaop.service.impl.MyBeanServiceImpl"></bean>
    <bean id="txManager" class="com.ifueen._05xmlaop.TxManager"></bean>

    <!-- 配置AOP -->
    <aop:config>
        <!--
        id:切点的名称
        execution是一个表达式,去执行方法
        *:代表任意返回值
        com.ifueen._05xmlaop.service:对应的包
        I*Service:对应的类
        *:所有的方法
        (..):方法里面任意参数
        -->
        <aop:pointcut id="pointcut" expression="execution(* com.ifueen._05xmlaop.service.I*Service.*(..))"/>

        <aop:aspect ref="txManager">
            <!-- 前置通知 -->
            <!--<aop:before method="begin" pointcut-ref="pointcut"></aop:before>-->
            <!-- 后置通知 -->
            <!--<aop:after-returning method="commit" pointcut-ref="pointcut"></aop:after-returning>-->
            <!-- 异常通知,如果要抓取异常的话需要在这里也要设置 -->
            <!--<aop:after-throwing method="rollback" pointcut-ref="pointcut" throwing="e"></aop:after-throwing>-->
            <!-- 最终通知 -->
            <!--<aop:after method="close" pointcut-ref="pointcut"></aop:after>-->
            <!-- 环绕通知 里面可以自定义-->
            <aop:around method="around" pointcut-ref="pointcut"></aop:around>
        </aop:aspect>
    </aop:config>


</beans>

使用注解配置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/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 扫描包路径 -->
    <context:component-scan base-package="com.ifueen._06annoaop"></context:component-scan>
    <!-- 支持AOP注解 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

自定义的事务类

package com.ifueen._06annoaop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * 注解实现的事务
 */
@Component
@Aspect  //AOP的类注解
public class TxManager {

    //设置切点
    @Pointcut("execution(* com.ifueen._06annoaop.service.I*Service.*(..))")
    public void pointcut(){}

    //前置通知
    /*@Before("pointcut()")*/
    public void begin(){
        System.out.println("开启事务");
    }
    //后置通知
    /*@AfterReturning("pointcut()")*/
    public void commit(){
        System.out.println("提交事务");
    }
    //异常通知
    /*@AfterThrowing(pointcut = "pointcut()",throwing = "e")*/
    public void rollback(Throwable e){
        System.out.println("回滚事务,异常的原因为"+e.getMessage());
    }
    //最终通知
    /*@After("pointcut()")*/
    public void close(){
        System.out.println("关闭资源");
    }

    //如果要使用环绕通知,需关闭前面的注解,不然可能引起冲突
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint point){
        Object object = null;
        try {
            //开启事务
            begin();
            //这里执行我们自己的代码
            object = point.proceed();
            //提交事务
            commit();
        } catch (Throwable throwable) {
            //回滚
            rollback(throwable);
            throwable.printStackTrace();
        }finally {
            //关闭
            close();
        }
        return object;
    }


}

发布了87 篇原创文章 · 获赞 7 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/f2315895270/article/details/102407324