Spring IOC和AOP理解,以及怎么解决循环依赖

2020-04-04 16:05:03来源:博客园 阅读 ()

新老客户大回馈,云服务器低至5折

  • IOC

IOC,控制反转(Inversion of Control),就是把对象的创建(即bean的new操作),交给Spring来实现。

通过XML配置:bean标签是用于配置被spring容器管理的bean信息,我们可以通过bean标签,完成IOC的配置。

  • 使用默认无参构造函数来创建类对象,并存入spring容器
<bean id="userService" class="com.xcj.spring.service.UserServiceImpl"></bean>
public class UserServiceImpl implements UserService {
    
    
}

 

  • 静态工厂方式
<!-- 使用StaticFactory类中的静态方法createDemoService创建对象,并存入spring容器(简单了解下,实际中基本不用) -->
<bean id="demoService" class="com.xcj.spring.factory.StaticFactory" factory-method="createDemoService"></bean>
public class StaticFactory {
    
    public static DemoService createDemoService() {
        
        return new DemoServiceImpl();
    }

}
public class DemoServiceImpl implements DemoService {

    
}

 

  • 实例工厂方式
<!-- 先把工厂的创建交给spring来管理,再在使用工厂的bean来调用里面的方法 -->
<bean id="instanceFactory" class="com.xcj.spring.factory.InstanceFactory"></bean>
<bean id="beanService" factory-bean="instanceFactory" factory-method="createBeanService"></bean>
public class InstanceFactory {

    public static BeanService createBeanService() {
        
        return new BeanServiceImpl();
    }
}
public class BeanServiceImpl implements BeanService {

    
}

 

DI,依赖注入(Dependency Injection),是spring IOC的具体实现,做的工作是Spring实例化bean对象后,对bean对象的属性信息进行赋值的操作。

依赖指的是bean实例中的属性,分为简单类型(8种基本类型和String类型)的属性、POJO类型的属性、集合数组类型的属性。

注入方式:构造器,set方法,注解,(还有使用p名称空间注入数据,本质上还是调用set方法)。

  • 构造器注入
<bean id="userDemoService" class="com.xcj.spring.service.UserDemoServiceImpl">
    <constructor-arg name="id" value="1"></constructor-arg>
    <constructor-arg name="name" value="zhangsan"></constructor-arg>
</bean>
public class UserDemoServiceImpl implements UserDemoService {
    
    private int id;
    
    private String name;
        
    public UserDemoServiceImpl(int id, String name) {
        this.id = id;
        this.name = name;
    }
}

 

  • set方法注入(手动装配,即XML方式)
<bean id="demoSetService" class="com.xcj.spring.service.DemoSetServiceImpl">
    <!-- List类型的属性 -->
    <property name="lists">
        <list>
            <value>11</value>
            <value>22</value>
        </list>
    </property>
    <!-- Set类型的属性 -->
    <property name="sets">
        <set>
            <value>111</value>
            <value>222</value>
        </set>
    </property>
    <!-- Map类型的属性 -->
    <property name="maps">
        <map>
            <entry key="111" value="111-01"/>
            <entry key="222" value="222-01"/>
        </map>
    </property>
    <!-- Properties类型 -->
    <property name="props">
        <props>
            <prop key="name">root</prop>
            <prop key="password">123456</prop>
        </props>
    </property>
</bean>
public class DemoSetServiceImpl implements DemoSetService {

    private List<Object> lists;

    private Set<Object> sets;

    private Map<String, Object> maps;

    private Properties props;

    public void setLists(List<Object> lists) {
        this.lists = lists;
    }

    public void setSets(Set<Object> sets) {
        this.sets = sets;
    }

    public void setMaps(Map<String, Object> maps) {
        this.maps = maps;
    }

    public void setProps(Properties props) {
        this.props = props;
    }

}

 

  • 注解(自动装配)

(1)@Autowired,按类型注入,要唯一;如果遇到相同的,则要加上@Qualifer,表示在类型注入基础上按名称注入。

(2)@Resource,按照bean的name/id注入。

@Service("userService")
public class UserServiceImpl implements UserSetService{
    
    @Autowired
    private UserDao userDao;

}

 

那么问题:Spring怎么解决循环依赖的?通过三级缓存。

 

 

  • AOP

AOP,面向切面编程(Aspect Oriented Programming),是一种编程范式,是OOP(面向对象编程)的延续,采用横向抽取机制,补充了OOP纵向继承体系无法解决的重复代码优化方式。

譬如,假设有A,B有相同的逻辑,我们可以横向抽取相同的部分出来,通过AOP思想和业务串联起来,同时这是可插拔式的。

AOP思想的实现一般都是基于代理模式,给业务代码进行功能增强,将业务代码和系统代码解耦。

如果目标对象的实现类实现了接口,Spring AOP 将会采用 JDK 动态代理来生成 AOP 代理类;

如果目标对象的实现类没有实现接口,Spring AOP 将会采用 CGLIB 来生成 AOP 代理类。

(1)使用XML方式实现

public class AopAdvice {
    
    public void saveLog() {
        System.out.println("保存日志");
    }

}

 

<bean name="aopAdvice" class="com.xcj.spring.advice.AopAdvice"></bean>

<aop:config>
    <aop:aspect ref="aopAdvice">
        <aop:before method="saveLog" pointcut="execution(* com.xcj.spring..*Service.do*(..))" />
    </aop:aspect>
</aop:config>

(2)使用注解实现

 

@Component("aopDemoAdvice")
@Aspect
public class AopDemoAdvice {
    
    @Before(value="execution(* com.xcj.spring..*Service.do*(..))")
    public void saveLog() {
        System.out.println("保存日志");
    }
}
<!-- Spring AOP,通过动态代理技术实现的,而动态代理是基于反射 -->
<!-- 开启注解并扫描指定包中带有注解的类 -->
<context:component-scan base-package="com.xcj.spring.service"></context:component-scan>

<!-- 开启AOP自动代理 -->
<aop:aspectj-autoproxy />

 

TODO

 


原文链接:https://www.cnblogs.com/scorpio-cat/p/12632063.html
如有疑问请与原作者联系

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:Java 程序该怎么优化?(工具篇)

下一篇: LeetCode 42. 接雨水