B057-spring增强 依赖注入 AOP 代理模式 创建Bean

这篇具有很好参考价值的文章主要介绍了B057-spring增强 依赖注入 AOP 代理模式 创建Bean。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

DI:依赖注入

环境准备,即写一个spring测试,见工程

构造器注入

即使用构造器来给Bean的对象的属性赋值

MyBean
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MyBean {
    private Long id;
    private String name;
    private OtherBean otherBean;
}
OtherBean
public class OtherBean {
}
SpringTest-Context.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">

<!--<constructor-arg 构造器注入 普通属性注入   index/name/type:下标/名称/类型,  value:赋值    -->
<!--    <bean id="myBean" class="cn.ming._01constructor.MyBean">-->
<!--     1.构造器注入,普通属性注入,index:下标,value:赋值  -->
<!--        <constructor-arg index="0" value="1"/>-->
<!--        <constructor-arg index="1" value="时光鸡11"/>-->
<!--     2.构造器注入,普通属性注入,name:名称,value:赋值  -->
<!--        <constructor-arg name="id" value="1"/>-->
<!--        <constructor-arg name="name" value="时光鸡12"/>-->
<!--     3.构造器注入,普通属性注入,type:类型,value:赋值。如果有重复类型就不能用这种,一般不用这种  -->
<!--        <constructor-arg type="java.lang.Long" value="1"/>-->
<!--        <constructor-arg type="java.lang.String" value="时光鸡13"/>-->
<!--     0.这是前面学过的setter方法注入,普通属性注入,name:属性名称 - set方法后面的属性,value:赋值  -->
<!--        <property name="id" value="123"></property>-->
<!--        <property name="name" value="王天霸"></property>-->
<!--    </bean>-->

    <!--引用属性注入-->
<!--    <bean id="otherBean" class="cn.itsource._01constructor.OtherBean"/>-->
<!--    <bean id="myBean" class="cn.itsource._01constructor.MyBean">-->
<!--        <constructor-arg index="0" value="1"/>-->
<!--        <constructor-arg index="1" value="时光鸡20"/>-->
            <!--引用外部bean-->
<!--        <constructor-arg index="2" ref="otherBean"/>-->
<!--    </bean>-->
    <!--引用属性注入-->
    <bean id="myBean" class="cn.itsource._01constructor.MyBean">
        <constructor-arg index="0" value="1"/>
        <constructor-arg index="1" value="时光鸡21"/>
        <!--引用内部bean -->
        <constructor-arg index="2">
            <bean class="cn.itsource._01constructor.OtherBean"/>
        </constructor-arg>
    </bean>

</beans>
SpringTest
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration//回到当前类的包下 查找当前类名-Context.xml的配置文件
public class SpringTest {
    @Autowired
    MyBean myBean;

    @Test
    public void testSpring(){
        System.out.println(myBean);
    }
}
setter方法注入

即用setter方法给bean对象的属性赋值

MyBean
@Data
public class MyBean {

    // 1.简单属性
    private Long id;
    private String name;
    private Boolean sex;
    private BigDecimal salary;

    // 2.普通集合属性
    private List<String> stringList;
    private Set<String> stringSet;

    // 3.引用集合属性
    private List<OtherBean> otherBeanList;
    private Set<OtherBean> otherBeanSet;

    // 4.数组
    private String[] arrays1;
    private String[] arrays2;

    // 5.properties
    private Properties props1;
    private Properties props2;

    @Override
    public String toString() {
        System.out.println("stringList======"+stringList);
        System.out.println("stringSet======"+stringSet);
        System.out.println("otherBeanList======"+otherBeanList);
        System.out.println("otherBeanSet======"+otherBeanSet);
        System.out.println("arrays1======"+ Arrays.asList(arrays1));
        System.out.println("arrays2======"+ Arrays.asList(arrays2));
        System.out.println("props1======"+ props1);
        System.out.println("props2======"+ props2);
        return "MyBean{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", sex=" + sex +
                ", salary=" + salary +
                '}';
    }
}
OtherBean
public class OtherBean {
}
SpringTest-Context.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">

    <bean id="otherBean" class="cn.itsource._02property.OtherBean"/>

    <bean id="myBean" class="cn.itsource._02property.MyBean">
        <property name="id" value="1"/>
        <property name="name" value="张三"/>
        <property name="sex" value="true"/>
        <property name="salary" value="10000000000"/>

        <property name="stringList">
            <list>
                <value>小红帽</value>
                <value>小红帽</value>
                <value>大红帽</value>
                <value>老红帽</value>
            </list>
        </property>
        <property name="stringSet">
            <set>
                <value>小红帽</value>
                <value>小红帽</value>
                <value>大红帽</value>
                <value>老红帽</value>
            </set>
        </property>

        <property name="otherBeanList">
            <list>
                <ref bean="otherBean"/>
                <ref bean="otherBean"/>
                <bean class="cn.itsource._02property.OtherBean"/>
                <bean class="cn.itsource._02property.OtherBean"/>
            </list>
        </property>

        <property name="otherBeanSet">
            <set>
                <ref bean="otherBean"/>
                <ref bean="otherBean"/>
                <bean class="cn.itsource._02property.OtherBean"/>
                <bean class="cn.itsource._02property.OtherBean"/>
            </set>
        </property>

        <!--完整写法-->
        <property name="arrays1">
            <array>
                <value>时,光鸡</value>
                <value>光鸡</value>
                <value></value>
            </array>
        </property>
        <!--简写 如果元素内有逗号会解析为分隔符,不推荐用这种-->
        <property name="arrays2" value="时光鸡,光鸡,鸡"/>

        <!--完整写法 支持中文-->
        <property name="props1">
            <props>
                <prop key="driver">com.mysql.jdbc.Driver</prop>
                <prop key="url">jdbc:mysql:///哈哈</prop>
            </props>
        </property>
        <!--简写 不支持中文-->
        <property name="props2">
            <value>
                driver=com.mysql.jdbc.Driver
                url=jdbc:mysql:///哈哈
            </value>
        </property>
    </bean>

</beans>
SpringTest
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration//回到当前类的包下 查找当前类名-Context.xml的配置文件
public class SpringTest {
    @Autowired
    MyBean myBean;

    @Test
    public void testSpring(){
        System.out.println(myBean);
    }
}

AOP

概念

B057-spring增强 依赖注入 AOP 代理模式 创建Bean,笔记总结,spring,代理模式,java
事务管理:比如可以抽取try catch的重复代码
日志监控:比如业务逻辑前后打印关于当前订单数量的日志,了解业务做了什么
性能监控:比如业务前后打印时间,相减可查看业务跑完所需时间

代理模式引出

B057-spring增强 依赖注入 AOP 代理模式 创建Bean,笔记总结,spring,代理模式,java
用aop实现扩展功能,
aop用代理模式实现,但是代理模式里的扩展功能还是需要我们自己写,

静态代理:相当于一个中介只代理一个固定的房东的房源,基本不用
动态代理:默认没有,使用的时候动态生成

AOP:以上大方向
SpringAOP:AOP的spring实现方式,用动态代理方式实现。它的实现方式又有两种:jdk,CGLIB,spring自动选择用其中哪种方式,代理类自动生成也不用管,有接口的时候默认使用jdk,没有的时候用cglib(第三方jar包),现在一般service都有接口

AOP实现方式
xml方式实现

1.编写TxManager用来提供业务逻辑外的扩展功能 - 如事务管理

/*我们自己的扩展功能*/
public class TxManager {

    public void open (){
        System.out.println("开启事务");
    }

    public void commit (){
        System.out.println("提交事务");
    }

    public void rollback(Throwable e){
        e.printStackTrace();//处理异常
        System.out.println("回滚事务");
    }

    public void close(){
    System.out.println("关闭事务");
    }

    public void around(ProceedingJoinPoint point){
        try {
            open();
            point.proceed();//执行真正的业务
            commit();
        } catch (Throwable e) {
            e.printStackTrace();
            rollback(e);
        } finally {
            close();
        }
    }
}

2.准备xmlAOP环境,在Spring配置文件中引入头支持以支持aop标签

SpringTest-Context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

3.配置的三要素
何时,如在业务的执行前、后、catch
何地,指的是在哪一个方法
做什么,执行我们自定义扩展业务类的方法

面向切面编程,面向扩展功能编程
B057-spring增强 依赖注入 AOP 代理模式 创建Bean,笔记总结,spring,代理模式,java
其他
spring通过动态代理实现aop,配置aop后只能注入接口,通过接口找到被引用的代理类,Spring容器中就只有代理类没有实现类,

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration//回到当前类的包下 查找当前类名-Context.xml的配置文件
public class SpringTest {

    @Autowired
    IUserService userService;

    @Test
    public void testUser(){
        System.out.println(userService.getClass());
    }
}

SpringTest-Context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="userService" class="cn.itsource._03aopxml.service.impl.UserServiceImpl"/>
    <bean id="departmentService" class="cn.itsource._03aopxml.service.impl.DepartmentServiceImpl"/>

    <!--将扩展功能交给Spring容器管理,方便AOP使用-->
    <bean id="txManager" class="cn.itsource._03aopxml.TxManager"/>
    <!--SpringAOP的核心配置-->
    <aop:config>
        <!--配置切点  配置何地 ==在哪一个方法执行
            expression:表达式  通过表达式,我们找在哪一个方法执行
            第一个*:任意返回值
            I*Service:所有以I开头 Service结尾的类(里面的所有方法都加上事物)
            第三个*:任意方法
            save(..):任意参数
        -->
        <!--execution(* cn.itsource._03aopxml.service.impl.UserServiceImpl.save(..))
            execution(* cn.itsource._03aopxml.service.impl.UserServiceImpl.*(..))-->
        <aop:pointcut id="txPoint" expression="execution(* cn.itsource._03aopxml.service.I*Service.*(..))"/>
        <!--配置切面   -->
        <aop:aspect ref="txManager">
            <!--配置前置通知 配置何时做什么-->
            <!--<aop:before method="open" pointcut-ref="txPoint"/>-->
            <!--配置后置通知-->
            <!--<aop:after-returning method="commit" pointcut-ref="txPoint"/>-->
            <!--配置异常通知-->
            <!--<aop:after-throwing method="rollback" pointcut-ref="txPoint" throwing="e"/>-->
            <!--配置最终通知-->
            <!--<aop:after method="close" pointcut-ref="txPoint"/>-->
            <!--配置环绕通知  环绕通知一行顶上面四行-->
            <aop:around method="around" pointcut-ref="txPoint"/>
        </aop:aspect>
    </aop:config>
</beans>

测试

详细见工程代码

注解方式实现

A 引入容器扫描头 Spring AOP

SpringTest-Context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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/aop http://www.springframework.org/schema/aop/spring-aop.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!--开启Spring注解扫描-->
    <context:component-scan base-package="cn.itsource._04aopanno"/>

    <!--开启SpringAOP 注解扫描-->
    <aop:aspectj-autoproxy/>

</beans>

后面的几步,都是在TxManager中完成
B 将扩展业务交给容器管理 @Component
C 申明pointcut,@Pointcut,需要提供一个空方法
D 配置各种通知
只用@Around环绕通知,其他四种通知不能确定执行顺序,

/*我们自己的扩展功能*/
@Component //组件 把当前类交给Spring容器管理
@Aspect //== <aop:aspect ref="txManager"> 配置切面
public class TxManager {

    //配置切点  == <aop:pointcut id="txPoint"
    @Pointcut("execution(* cn.itsource._04aopanno.service.I*Service.*(..))")
    public void  txPoint(){
        /*这个方法指明在业务类中的每个方法*/
    }

    /*配置前置通知*/
    /*@Before("txPoint()")*/
    public void open (){
        System.out.println("开启事物");
    }

    /*@AfterReturning("txPoint()")*/
    public void commit (){
        System.out.println("提交事物");
    }

    /*@AfterThrowing(value = "txPoint()", throwing = "e")*/
    public void rollback(Throwable e){
        e.printStackTrace();//处理异常
        System.out.println("回滚事务");
    }

    /*@After("txPoint()")*/
    public void close(){
    System.out.println("关闭事物");
    }

    @Around("txPoint()")
    public void around(ProceedingJoinPoint point){
        try {
            open();
            point.proceed();//执行真正的业务
            commit();
        } catch (Throwable e) {
            e.printStackTrace();
            rollback(e);
        } finally {
            close();
        }
    }
}

测试

详细见工程代码

Spring创建Bean

直接创建

以上创建方式都属于直接创建,如文章来源地址https://www.toymoban.com/news/detail-656545.html

<bean id="userService" class="cn.ming._03aopxml.service.impl.UserServiceImpl"/>
工厂类的静态方法创建
Car
public class Car {
}
CarFactory
public class CarFactory {
    public static Car createCar(){
        return new Car();
    }
}
SpringTest-Context.xml
<bean id="car" class="cn.itsource._05create._02.CarFactory" factory-method="createCar"/>
SpringTest
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration//回到当前类的包下 查找当前类名-Context.xml的配置文件
public class SpringTest {
    @Autowired
    Car car;
    
    @Test
    public void testUser() {
        System.out.println(car);
    }
}
工厂类的非静态方法创建
Car
public class Car {
}
CarFactory
public class CarFactory {
    public Car createCar(){
        return new Car();
    }
}
SpringTest-Context.xml
    <bean id="carFactroy" class="cn.itsource._05create._03.CarFactory"/>
    <bean id="car" factory-bean="carFactroy" factory-method="createCar"/>
SpringTest
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration//回到当前类的包下 查找当前类名-Context.xml的配置文件
public class SpringTest {
    @Autowired
    Car car;
    
    @Test
    public void testUser() {
        System.out.println(car);
    }
}
FactoryBean方式创建
Car
public class Car {
}
CarFactoryBean
public class CarFactoryBean implements FactoryBean<Car> {

    // 设置返回的bean
    @Override
    public Car getObject() throws Exception {
        return new Car();
    }

    // 设置返回值类型
    @Override
    public Class<?> getObjectType() {
        return Car.class;
    }

    // 设置是否单例
    @Override
    public boolean isSingleton() {
        return true;
    }
}
SpringTest-Context.xml
    <!--ctrl + alt + l
        Spring中,扫描到你当前类是FactoryBean的类,他会调用getObject(),将方法的返回值作为对象管理起来
                 通过getObjectType()的返回值确定类型                  -->
    <bean id="car" class="cn.itsource._05create._04.CarFactoryBean"/>
SpringTest
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration//回到当前类的包下 查找当前类名-Context.xml的配置文件
public class SpringTest {
    @Autowired
    Car car;
    @Autowired
    Car car2;
    @Test
    public void testCar(){
        System.out.println(car);
        System.out.println(car2);
    }
}

到了这里,关于B057-spring增强 依赖注入 AOP 代理模式 创建Bean的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring入门&控制反转(或依赖注入)&AOP的关键概念& 多配置文件&与web集成

    目录 1. 什么是spring,它能够做什么? 2. 什么是控制反转(或依赖注入) 3. AOP的关键概念 4. 示例 4.1 创建工程 4.2 pom文件 4.3 spring配置文件 4.4 示例代码 4.4.1 示例1 4.4.2 示例2 (abstract,parent示例) 4.4.3 使用有参数构造方法创建javaBean 4.4.4 init-method:指定bean的初始化方法 4.4.5 复杂属

    2024年02月09日
    浏览(32)
  • Spring 使用注解开发、代理模式、AOP

    在Spring4之后,要使用注解开发,必须要保证AOP的包导入了 项目搭建: 在配置文件中导入约束,增加注解支持 bean 实体类 @Component 注解 xml配置 测试: 属性如何注入 衍生的注解 @Component 有几个衍生的注解,我们在web开发中,会按照MVC三层架构分层 dao层: @Repository 等价于poj

    2024年02月13日
    浏览(33)
  • 54.Spring的AOP是在哪里创建的动态代理?

    正常的Bean会在Bean的生命周期的‘初始化’后, 通过BeanPostProcessor.postProcessAfterInitialization创建aop的动态代理 还有一种特殊情况: 循环依赖的Bean会在Bean的生命周期‘属性注入’时存在的循环依赖的情况下, 也会为循环依赖的Bean 通过MergedBeanDefinitionPostProcessor.postProcessMergedBe

    2024年02月02日
    浏览(27)
  • Java Spring IoC&DI :探索Java Spring中控制反转和依赖注入的威力,增强灵活性和可维护性

    💓 博客主页:从零开始的-CodeNinja之路 ⏩ 收录文章:Java Spring IoCDI :探索Java Spring中控制反转和依赖注入的威力,增强灵活性和可维护性 🎉欢迎大家点赞👍评论📝收藏⭐文章 我们一下要学习的内容都是为了实现⾼内聚低耦合来进行的 软件设计原则:⾼内聚低耦合. ⾼内聚指

    2024年04月15日
    浏览(36)
  • Spring AOP (面向切面编程)原理与代理模式—实例演示

    Spring 中文文档 (springdoc.cn) Spring | Home 官网         Java是一个面向对象(OOP)的语言,但它有一些弊端。虽然使用OOP可以通过组合或继承的方式来实现代码的重用。但当我们需要为多个不具有继承关系的对象(一般指的是两个不同的类,它们之间没有继承自同一个父类或接

    2024年02月15日
    浏览(39)
  • Spring学习笔记(二)Spring的控制反转(设计原则)与依赖注入(设计模式)

    是一种设计原则,降低程序代码之间的耦合度 对象由Ioc容器统一管理,当程序需要使用对象时直接从IoC容器中获取。这样对象的控制权就从应用程序转移到了IoC容器 依赖注入是一种消除类之间依赖关系的设计模式。例如,A类要依赖B类,A类不再直接创建B类,而是把这种依赖

    2024年02月19日
    浏览(28)
  • Spring5学习随笔-IOC(反转控制)、DI(依赖注入)和创建复杂对象

    学习视频:【孙哥说Spring5:从设计模式到基本应用到应用级底层分析,一次深入浅出的Spring全探索。学不会Spring?只因你未遇见孙哥】 控制:对于成员变量赋值的控制权 反转控制:把对于成员变量赋值的控制权,从代码中反转(转移)到Spring工厂和配置文件中。 好处:解耦合

    2024年02月05日
    浏览(30)
  • 【Spring教程十】Spring框架实战:全面深入详解IOC/DI之--纯注解开发模式下的依赖注入&&注解读取properties配置文件

    欢迎大家回到《 Java教程之Spring30天快速入门》,本教程所有示例均基于Maven实现,如果您对Maven还很陌生,请移步本人的博文《 如何在windows11下安装Maven并配置以及 IDEA配置Maven环境》,本文的上一篇为《 全面深入详解IOC/DI注解开发》 Spring为了使用注解简化开发,并没有提供

    2024年02月04日
    浏览(44)
  • Spring | Srping AOP (AOP简介、动态代理、基于“代理类”的AOP实现)

    作者简介 :一只大皮卡丘,计算机专业学生,正在努力学习、努力敲代码中! 让我们一起继续努力学习! 该文章 参考学习教材 为: 《Java EE企业级应用开发教程 (Spring + Spring MVC +MyBatis)》 黑马程序员 / 编著 文章以课本知识点 + 代码为主线,结合自己看书学习过程中的理解和

    2024年01月22日
    浏览(27)
  • Spring AOP与静态代理/动态代理

    代理模式是一种结构型设计模式,它允许对象提供替代品或占位符,以控制对这个对象的访问。代理对象通常充当客户端和实际服务对象之间的中介,以实现对服务对象的间接访问。 代理模式的实现有许多种方式,其中最常见的方式是静态代理和动态代理。 静态代理是指,

    2024年02月10日
    浏览(21)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包