Spring的依赖注入和AOP使用详解


Spring的依赖注入和AOP使用详解

一. 需要的POM.xml依赖


<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.0modelVersion>

    <groupId>com.lqsgroupId>
    <artifactId>spring-aop-demoartifactId>
    <version>1.0-SNAPSHOTversion>

    <properties>
        <maven.compiler.source>8maven.compiler.source>
        <maven.compiler.target>8maven.compiler.target>
    properties>

    
    <dependencies>
        
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-coreartifactId>
            <version>4.2.5.RELEASEversion>
        dependency>
        
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-contextartifactId>
            <version>4.2.5.RELEASEversion>
        dependency>
        
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-aopartifactId>
            <version>4.2.5.RELEASEversion>
        dependency>
        
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-testartifactId>
            <version>4.2.5.RELEASEversion>
        dependency>
        
        <dependency>
            <groupId>org.aspectjgroupId>
            <artifactId>aspectjweaverartifactId>
            <version>1.8.8version>
        dependency>
        
        <dependency>
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
            <version>4.12version>
        dependency>

        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-expressionartifactId>
            <version>4.2.5.RELEASEversion>
        dependency>

        <dependency>
            <groupId>commons-logginggroupId>
            <artifactId>commons-loggingartifactId>
            <version>1.1.2version>
        dependency>

        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <version>1.18.8version>
        dependency>
    dependencies>

    <build>
        
        <resources>
            <resource>
                <directory>src/main/javadirectory>
                <includes>
                    <include>**/*.xmlinclude>
                includes>
            resource>
            <resource>
                <directory>src/test/javadirectory>
                <includes>
                    <include>**/*.xmlinclude>
                includes>
            resource>
        resources>
    build>
project>

二. DI依赖注入

1. 构造器注入

  1. 1 实体类
    @Data
    public class MyBean {
        private Long id;
        private String username;
        private YouBean youBean;
    
        public MyBean(Long id, String username) {
            this.id = id;
            this.username = username;
        }
    
        public MyBean(Long id, String username, YouBean youBean) {
            this.id = id;
            this.username = username;
            this.youBean = youBean;
        }
    }
    
    @Data
    public class YouBean {
        private Long id;
        private String username;
    }
    
  2. applicationContext.xml

    
    <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: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/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">
        
        
        
    
        
        <bean id="myBean" class="com.lqs.constructor.domain.MyBean">
            
            
            
    
            
            
            
    
            
            
            
    
            <constructor-arg name="id" value="10086"/>
            <constructor-arg name="username" value="admin"/>
            
    
            
            <constructor-arg name="youBean">
                <bean class="com.lqs.constructor.domain.YouBean"/>
            constructor-arg>
        bean>
    
        <bean id="youBean" class="com.lqs.constructor.domain.YouBean"/>
      
      beans>
    

2. property-setter注入

2.1 Bean
@Data
@NoArgsConstructor
public class MyBean2 {
    // 简单属性
    private Long id;
    private String name;
    private Boolean sex;
    private BigDecimal salary;
    // 集合属性
    private String[] arrays;
    private List<String> list;
    private List<OtherBean> otherBeanList;
    private Set<String> set;
    private Set<OtherBean> otherBeanSet;
    //	更多用来写配置文件,Alt+回车 导包
	//	老项目,就很有可能会用到它
    private Properties props1;
    private Properties props2;
    }
public class OtherBean {
}
2.2 简单属性
<bean id="myBean2" class="com.lqs.property.domain.MyBean2">
        <property name="id" value="10086"/>
        <property name="name" value="root"/>
        <property name="sex" value="true"/>
        <property name="salary" value="8888.9999"/>
bean>
2.3 集合属性
 <bean id="myBean2" class="com.lqs.property.domain.MyBean2">

        <property name="arrays">
            <array>
                <value>JOJOvalue>
                <value>迪奥value>
                <value>小吴value>
            array>
        property>

        <property name="list">
            <list>
                <value>110value>
                <value>119value>
                <value>120value>
                <value>初音未来value>
            list>
        property>


        <property name="otherBeanList">
            <list>
                
                <bean class="com.lqs.property.domain.OtherBean"/>
                <bean class="com.lqs.property.domain.OtherBean"/>

                
                <ref bean="otherBean"/>
                <ref bean="otherBean"/>
            list>
        property>

        <property name="set">
            <set>
                <value>张三value>
                <value>李四value>
                <value>王五value>
                <value>王五value>
            set>
        property>

        <property name="otherBeanSet">
            <set>
                <bean class="com.lqs.property.domain.OtherBean"/>
                <bean class="com.lqs.property.domain.OtherBean"/>
                
                <ref bean="otherBean"/>
                <ref bean="otherBean"/>
            set>
        property>
 bean>
2.4 properties
 <bean id="myBean2" class="com.lqs.property.domain.MyBean2">
<property name="props1">
            
            <props>
                <prop key="1">001prop>
                <prop key="2">002prop>
                <prop key="特点">自律prop>
            props>
        property>

        
        <property name="props2">
            <value>
                name=admin
                id=007
                sex="true"
            value>
        property>
  bean>

三. AOP

1. 什么是AOP

AOP:全称是Aspect Oriented Programming 即:面向切面编程。通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生泛型。利用AOP可以对业务逻辑的各部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

简单的说它就是把我们程序重复的代码抽取出来,在需要执行的时候,使用动态代理的技术,在不修改源码的基础上,对我们的已有方法进行增强。

2. AOP实现方式
  • 使用动态代理技术。

    Spring的依赖注入和AOP使用详解_第1张图片

3. 代理模式
  • SpringAOP底层是使用了代理模式对我们的方法进行增强;
  • 代理模式分类:
    • 静态代理:作用不大,只能代理或增强一个方法,比较鸡肋
    • 动态代理:功能强大,有两种方案,Spring会自动选择使用那种方案
      • 方案一:原生JDK的方式,在我们的类实现了接口之后,就会使用这种方式,spring使用JDK的java.lang.reflect.Proxy类代理,推荐使用,更加解耦
      • 方案二:我如果我们的类没有实现接口,那么Spring使用CGLIB库生成目标对象的子类。

四. aop的xml实现方式

  1. Bean

    @Component
    public class TxManager {
        public void begin() {
            System.out.println("开启事务......");
        }
    
        public void commit() {
            System.out.println("提交事务......");
        }
    
        public void rollback(Throwable e) {
            System.out.println("回滚事务......");
            System.out.println(e.getMessage());
        }
    
        public void close() {
            System.out.println("关闭连接......");
        }
        
        //环绕通知
        public void around(ProceedingJoinPoint joinPoint) {
            begin();
            try {
                joinPoint.proceed();
                commit();
            } catch (Throwable e) {
                e.printStackTrace();
                rollback(e);
            } finally {
                close();
            }
        }
    }
    
  2. 接口

    package com.lqs.aop_xml.service;
    
    public interface IUserService {
        void add();
    
        void update();
    
        void delete();
    }
    
  3. 配置

    
        <aop:config>
            
            <aop:pointcut id="pointcut" expression="execution(* com.lqs.aop_xml.service.IUserService.*(..))"/>
            
            <aop:aspect ref="txManager">
                
                
                
                
                
                
                
                
    
                
                <aop:around method="around" pointcut-ref="pointcut"/>
            aop:aspect>
        aop:config>
    

五. aop的注解实现方式

  1. 配置注解扫描路径和开启动态代理

    <context:component-scan base-package="com.lqs.aop_xml"/>
    <context:component-scan base-package="com.lqs.aop_anno"/>
    
    <aop:aspectj-autoproxy/>
    
  2. 增强类

    package com.lqs.aop_anno;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.*;
    import org.springframework.stereotype.Component;
    
    @Component
    @Aspect//定义一个切面
    public class TxManager2 {
        //定义切点 空的方法体
        @Pointcut("execution(* com.lqs.aop_anno.service.IUserService2.*(..))")
        public void pointCut() {
        }
    
    
        //    @Before("pointCut()")
        public void begin() {
            System.out.println("开启事务......");
        }
    
        //    @AfterReturning("pointCut()")
        public void commit() {
            System.out.println("提交事务......");
        }
    
        //    @AfterThrowing(value = "pointCut()", throwing = "e")
        public void rollback(Throwable e) {
            System.out.println("回滚事务......");
            System.out.println(e.getMessage());
        }
    
    //        @After("pointCut()")
        public void close() {
            System.out.println("关闭连接......");
        }
    
        //环绕通知  不与其它通知一起用
        @Around("pointCut()")
        public void around(ProceedingJoinPoint joinPoint) {
            begin();
            try {
                joinPoint.proceed();
                commit();
            } catch (Throwable e) {
                e.printStackTrace();
                rollback(e);
            } finally {
                close();
            }
        }
    }
    
    

六. spring创建bean的四种方式

  1. 普通方式-通过公共无参进行实例化

    
    <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.lqs.bean.domain.MyBean"/>
    
    beans>
    
  2. 集成静态简单工厂

    // 此工厂生产MyBean
    public class MyBeanFactory {
        // 此方法是一个静态方法,用来生产MyBean
        public static MyBean getMyBean(){
            return  new MyBean();
        }
    }
    
     
            <bean class="com.lqs.bean.MyFactoryBean" factory-method="getMyBean"/>
    
  3. 集成实例简单工厂

    • 与第二种的区别就是,当你的工厂方法不是静态方法时,无法通过类名.方法名调用

      public class MyFactoryBean {
      //    public static MyBean getMyBean() {
      //        return new MyBean();
      //    }
      
          public  MyBean getMyBean() {
              return new MyBean();
          }
      }
      
       
              <bean id="myFactoryBean" class="com.lqs.bean.MyFactoryBean"/>
           <bean id="myBean" factory-bean="myFactoryBean" factory-method="getMyBean"/>
      
  4. 使用FactoryBean

    package com.lqs.bean;
    
    import com.lqs.bean.domain.MyBean;
    import org.springframework.beans.factory.FactoryBean;
    
    // FactoryBean:实现一个FactoryBean接口,并指定要生产的Bean对象
    public class MyBeanFactoryBean implements FactoryBean<MyBean> {
      
        // 此方法指定你要生产的bean对象
        public MyBean getObject() throws Exception {
            return new MyBean();
        }
        // 此方法指定你生产的bean的类型,必须指定否则报错
        public Class<?> getObjectType() {
            return MyBean.class;
        }
        // 此方法指定你生产的bean是否是单例的,默认false
        public boolean isSingleton() {
            return true;
        }
    }
    
    
        <bean id="myBeanFactoryBean" class="com.lqs.bean.MyBeanFactoryBean"/>
    

七. FactoryBean和BeanFactory的区别

BeanFactory是个Factory,也就是IOC容器或对象工厂,FactoryBean是个Bean。在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的。但对FactoryBean而言,这个Bean不是简单的Bean,而是一个能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似。

你可能感兴趣的:(笔记,spring,java,junit)