SpringAop1

本文深入探讨了Spring框架中的依赖注入技术,包括XML配置、注解、内部与外部Bean注入等不同方式,以及如何通过代理模式实现AOP的增强。

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

1.依赖注入

1.导包

<?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>cn.itsource</groupId>
    <artifactId>SpringAoc</artifactId>
    <version>1.0-SNAPSHOT</version>




<properties>
    <org.springframework.version>4.2.5.RELEASE</org.springframework.version>
</properties>


    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>${org.springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${org.springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${org.springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${org.springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${org.springframework.version}</version>
        </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.16.20</version>
    </dependency>
</dependencies>
    <build>
        <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>

bean注入

<!--set方法注入:只要写了bean标签,就要求类中必须要有无参构造方法只要写了property标签,就一定是利用属性的set方法注入对象-->
    <bean id="userDao" class="cn.itsource._01_DI_bean.dao.impl.UserDaoImpl"></bean>
    <bean id="userService" class="cn.itsource._01_DI_bean.service.impl.UserServiceImpl">
        <!--  property标签表示属性,name表示属性名称,ref表示引用另一个bean标签的id  -->
        <property name="userDao" ref="userDao"/>
    </bean>
    <bean id="userController" class="cn.itsource._01_DI_bean.controller.UserController">
        <property name="userService" ref="userService"/>
    </bean>

构造器注入

<!--
        构造方法注入:
        只要写了bean标签,就要求类中必须要有无参构造方法
            constructor 构造方法-arg  argument参数  构造方法参数
            ① 按构造方法的参数名称注入【推荐】
            ② 按构造方法的参数顺序注入【推荐】
            ③ 按构造方法的参数类型注入【一般不用这个,因为有可能出现构造方法参数的类型是相同的情况,那么还要再按照顺序来注入】
    -->
    <bean id="userDao" class="cn.itsource._02_DI_constructor.dao.impl.UserDaoImpl">
        <constructor-arg type="java.lang.String" value="DAO层" />
        <constructor-arg type="java.lang.String" value="3层" />
    </bean>
    <bean id="userService" class="cn.itsource._02_DI_constructor.service.impl.UserServiceImpl">
        <constructor-arg name="userDao" ref="userDao" />
    </bean>
    <bean id="userController" class="cn.itsource._02_DI_constructor.controller.UserController">
        <constructor-arg index="0" ref="userService" />
    </bean>

注解注入

<?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="cn.itsource._03_DI_annotation"></context:component-scan>

        <context:annotation-config></context:annotation-config>


</beans>

内部的Bean注入

  <!--
        set方法注入:
        只要写了bean标签,就要求类中必须要有无参构造方法
            只要写了property标签,就一定是利用属性的set方法注入对象
            property标签表示属性,name表示属性名称,ref表示引用另一个bean标签的id
        外部bean:
            需要使用ref属性去引用另一个bean标签的id
            <property name="userDao" ref="userDao"/>
        内部bean:
            在property标签内部写一个bean标签,这个bean标签就可以不写id属性了
            <property name="userDao">
                <bean class="cn.itsource._04_DI_innerOrOuterBean.dao.impl.UserDaoImpl"></bean>
            </property>
    -->
    <!--
    外部bean的写法:
    <bean id="userDao" class="cn.itsource._04_DI_innerOrOuterBean.dao.impl.UserDaoImpl"></bean>
    <bean id="userService" class="cn.itsource._04_DI_innerOrOuterBean.service.impl.UserServiceImpl">
        <property name="userDao" ref="userDao"/>
    </bean>-->

    <!-- 内部bean的写法 -->
    <bean id="userService" class="cn.itsource._04_DI_innerOrOuterBean.service.impl.UserServiceImpl">
        <property name="userDao">
            <bean class="cn.itsource._04_DI_innerOrOuterBean.dao.impl.UserDaoImpl"></bean>
        </property>
    </bean>
    <bean id="userController" class="cn.itsource._04_DI_innerOrOuterBean.controller.UserController">
        <property name="userService" ref="userService"/>
    </bean>

set

package cn.itsource._05_set;

import lombok.Data;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

@Data
public class Person {
    //  简单属性【8种基本数据类型及其包装类型,String/BigDecimal】
    private Long id;
    private String name;
    private Boolean sex;
    private BigDecimal salary;

    // 对象属性
    private OtherBean otherBean;
    private String[] arrays;
    private List<String> list;
    private Set<String> set;


    //下面这个是重点
    private Properties props1;
    private Properties props2;
    private List<OtherBean> otherBeanList;
    private Set<OtherBean> otherBeanSet;
    private Map<String, Object> map;

}

package cn.itsource._05_set;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:cn/itsource/_05_set/spring.xml")
public class DiTest {
        @Autowired
    private Person person;
        @Test
        public void test()throws Exception{
            System.out.println(person);
        }
}

package cn.itsource._05_set;

public class OtherBean {
}

<?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="cn.itsource._05_set.Person" autowire="byType">
        <property name="id" value="1"></property>
        <property name="name" value="小猪"></property>
        <property name="sex" value="false"></property>
        <property name="salary" value="3000"></property>

        <property name="arrays">

            <array>
                <value>x</value>
                <value>y</value>
                <value>z</value>
            </array>
        </property>

        <property name="list">
            <list>
                <value></value>
                <value></value>
                <value></value>
                <value></value>
            </list>
        </property>

        <property name="set">

            <set>
                    <value></value>
                    <value></value>
                    <value></value>
                    <value></value>
            </set>
        </property>
        
        <property name="props1">
            <props>
                <prop key="name">小猪</prop>
                <prop key="age">3</prop>
            </props>
        </property>

        <property name="props2">
            <value>
                name=x
                age=3
            </value>
        </property>

        <property name="map">

            <map>
                <entry key="1" value="小猪"></entry>
                <entry key="2" value="小虎"></entry>
                <entry key="3" value="33"></entry>

            </map>
        </property>

        <property name="otherBean" ref="otherBean01"></property>

        <property name="otherBeanList">
            <list>
                <ref bean="otherBean02"></ref>
                <ref bean="otherBean03"></ref>
                <ref bean="otherBean04"></ref>
                <ref bean="otherBean01"></ref>
            </list>
        </property>

        <property name="otherBeanSet">

            <set>
                <ref bean="otherBean02"></ref>
                <ref bean="otherBean01"></ref>
                <ref bean="otherBean03"></ref>
                <ref bean="otherBean04"></ref>
            </set>
        </property>
    </bean>
    <bean id="otherBean01" class="cn.itsource._05_set.OtherBean"></bean>
    <bean id="otherBean02" class="cn.itsource._05_set.OtherBean"></bean>
    <bean id="otherBean03" class="cn.itsource._05_set.OtherBean"></bean>
    <bean id="otherBean04" class="cn.itsource._05_set.OtherBean"></bean>
</beans>

代理模式

代理模式定义
代理模式的英文叫做Proxy或Surrogate,中文都可译为”代理“,所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动。在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用
定义可以比较难以理解,咱们把这个抽象的概念换成咱们现实中的代理:
火车票代理点
房屋中介
小王的好朋友小宋
开发术语
① 抽象主题角色:
声明了真实主题和代理主题的共同接口,这样一来在任何可以使用真实主题的地方都可以是使用代理主题。

② 代理主题(Proxy)角色:
代理主题角色内部含有对真实主题的引用,从而可以在任何时候操作真实主题对象;
代理主题角色提供一个与真实主题角色相同的接口,以便可以在任何时候都可以替代真实主题控制对真实主题的引用,负责在需要的时候创建真实主题对象(和删除真实主题对象);
代理角色通常在将客户端调用传递给真实的主题之前或之后(前置增强/通知,后置增强/通知),都要执行某个操作,而不是单纯地将调用传递给真实主题对象。

③ 真实主题角色:
定义了代理角色所代表地真实对象

1.静态代理

package cn.itsource._06_proxy_static;

public interface IRent {
    //收钱
    void rent();
    //签合同
    void asign();
}

package cn.itsource._06_proxy_static;

public class Intermidary implements IRent{
    private IRent iRent;

    public Intermidary(IRent iRent) {
        this.iRent = iRent;
    }

    public void rent() {
        System.out.println("调用之前插入逻辑");
        this.iRent.rent();
        System.out.println("调用之后插入逻辑");
    }

    public void asign() {
        System.out.println("调用之前加入逻辑");
        this.iRent.asign();
        System.out.println("调用之后加入逻辑");
    }
}

package cn.itsource._06_proxy_static;

public class Landlord implements IRent {
    public void rent() {
        System.out.println("房东收钱");
    }

    public void asign() {
        System.out.println("房东签合同");
    }
}

package cn.itsource._06_proxy_static;

import org.junit.Test;

public class StaticProxyTest {
    @Test
    public void test()throws Exception{
        Landlord landlord = new Landlord();
        Intermidary intermidary = new Intermidary(landlord);
        intermidary.rent();
        intermidary.asign();
    }
}

2.动态代理

package cn.itsource._07_proxy_dynamic;
//抽象主题角色
public interface IRent {
    //收钱
    void rent();
    //签合同
    void asign();
}

package cn.itsource._07_proxy_dynamic;

public interface ITicket {
    //订票
    void order();
}

package cn.itsource._07_proxy_dynamic;

//房东:真实角色
public class Landlord implements IRent,ITicket{
    public void rent() {
        System.out.println("房东收钱");
    }

    public void asign() {
        System.out.println("房东签合同");
    }

    public void order() {
        System.out.println("订火车票");
    }
}

package cn.itsource._07_proxy_dynamic;


import org.junit.Test;
import org.springframework.cglib.proxy.InvocationHandler;
import org.springframework.cglib.proxy.Proxy;

public class DynamicProxyTest {
    @Test
    public void test()throws Exception{
        /**
         * ClassLoader loader 类加载器
         * Class<?>[] interfaces 被代理对象实现的所有接口形成的数组
         * InvocationHandler h 执行处理器
         */
      //  ClassLoader loader = DynamicProxyTest.class.getClassLoader();
        ClassLoader loader = Thread.currentThread().getContextClassLoader();//支持多线程并发

        //创建一个被代理对象(真实主题角色)
        IRent rent = new Landlord();
        //获取被代理对象类实现过的所有接口,返回一个数组
        Class<?>[] interfaces = rent.getClass().getInterfaces();
        //执行处理器
        InvocationHandler h = new MyInvocationHandler(rent);


        //调用JDK自带的动态代理技术生成代理对象
        IRent proxy = (IRent) Proxy.newProxyInstance(loader, interfaces,h);

        System.out.println(proxy);
        System.out.println(proxy.getClass());

        proxy.asign();
        proxy.rent();
    }
}

package cn.itsource._07_proxy_dynamic;

import org.springframework.cglib.proxy.InvocationHandler;

import java.lang.reflect.Method;

public class MyInvocationHandler implements InvocationHandler {
    private Object target;

    public MyInvocationHandler(Object target) {
        this.target = target;
    }


    public Object invoke(Object o, Method method, Object[] args ) throws Throwable {
        //方法调用之前插入业务逻辑
        System.out.println("方法调用之前插入业务逻辑");
        //使用反射技术调用被代理对象的该方法
        Object result = method.invoke(target, args);
        //方法调用之后插入业务逻辑
        System.out.println("方法调用之后插入业务逻辑");
        return result;
    }
}

在这里插入图片描述
底层

package cn.itsource._07_proxy_dynamic;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class $Proxy4 implements IRent,ITicket {

    private Object target;

    public $Proxy4(Object target) {
        this.target = target;
    }

    public void rent() {
        System.out.println("调用方法之前插入业务逻辑");

        try {
            Method rent = target.getClass().getDeclaredMethod("rent");
            rent.invoke(target);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        System.out.println("调用方法之后插入业务逻辑");
    }

    public void asign() {
        System.out.println("调用方法之前插入业务逻辑");
        try {
            Method rent = target.getClass().getDeclaredMethod("asign");
            rent.invoke(target);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        System.out.println("调用方法之后插入业务逻辑");
    }

    public void order() {
        System.out.println("调用方法之前插入业务逻辑");
        try {
            Method rent = target.getClass().getDeclaredMethod("order");
            rent.invoke(target);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        System.out.println("调用方法之后插入业务逻辑");
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值