Spring不同装配方式,代理模式,aop
使用注解开发
-
bean
-
属性如何注入
//等价于
//@Compoent 组件
@Component
public class User {
//相当于:public String name; @Value("cch2") public void setName(String name) { this.name = name; }}
-
衍生注解
@Component有几个衍生注解,我们在web开发中,会按照mvc三层架构分层
- dao 【@Repository】
- service【@Service】
- controller【@Controller】
这四个注解功能都是一样的,都是代表将某个类注册到Spring中,装配Bean
-
自动装配
- @Autowired:自动装配,通过类型。名字
如果Autowired不能唯一自动装配属性,则需要通过@Qualifier(value = "xxx") - @Nullable 字段标记了这个注解,说明这个字段可以为null;
- @Resource: 自动装配,通过名字。类型
- @Autowired:自动装配,通过类型。名字
作用域
@Component
@Scope("singleton")
public class User {
//相当于:<property name="name" value="cch2"/>
public String name;
@Value("cch2")
public void setName(String name) {
this.name = name;
}
}
小结
xml与注解:
- xml更加万能,适用于任何场合 。维护简单方便
- 注解:不是自己的类使用不了,维护相对复杂
xml与注解最佳实践:
-
xml用来管理bean;
-
注解只负责完成属性的注入;
-
我们在使用的过程中,只需要注意一个问题:必须让注解实效,就需要开启注解的支持
<context:component-scan base-package="com.king"/> <context:annotation-config/>
使用java的方式配置Spring
实体类
//这里这个注解的意思,就是说明这个类被Spring接管了,注册到了容器中
@Component
public class User {
private String name;
public String getName() {
return name;
}
@Value("xsb")//属性注入值
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
配置文件
//这个也会被Spring容器托管,注册到容器中,他本来就是@Component,
// @Configuration 代表这是一个配置类,就和我们之前看到的bean.xml
@Configuration
@ComponentScan("com.kua.pojo")
@Import(MyConfig2.class)
public class MyConfig {
//注册一个bean,就相当于我们之前写的一个bean标签
//这个方法的名字,就相当于标签中的id属性
//这个方法的返回值,就相当于bean标签中的class属性
@Bean
public User getUser(){
return new User();//就是返回要注入到bean的对象
}
}
测试类
public class MyTest {
public static void main(String[] args) {
//如果完全使用了配置类的方式去做,我们就只能通过ApplicationConfig 上下文来获取容器,通过配置类的class对象加载
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
User user = context.getBean("getUser", User.class);
System.out.println(user.getName());
}
}
这种纯java的配置方式,在SpringBoot中随处可见
代理模式
SpringAOP的底层就是代理模式
代理模式的分类:
- 静态代理
角色分析:
- 抽象角色:一般会使用接口或者抽象类来决定
- 真实角色:被代理的角色
- 代理角色:代理真实对象,代理真实角色后,我们一般会 做一些附属操作
- 客户:访问代理对象的人
代码步骤:
-
接口
public interface Rent {
public void rent();
} -
真实角色
//房东
public class Host implements Rent{public void rent() { System.out.println("房东要出租房子"); } } -
代理角色
public class Proxy implements Rent{
private Host host;public Proxy() { } public Proxy(Host host) { this.host = host; } public void rent() { host.rent(); seeHouse(); fare(); ht(); System.out.println("中介代你向房东租房"); } //看房 public void seeHouse(){ System.out.println("中介带你看房"); } //收中介费 public void fare(){ System.out.println("收中介费"); } //签租赁合同 public void ht(){ System.out.println("签租赁合同"); } } -
客户端访问代理角色
public class Client {
public static void main(String[] args) {
//房东要出租房子
Host host = new Host();
//代理,中介棒房东出租房子,但是呢。同时代理角色一般有一些附属操作
Proxy proxy = new Proxy(host);
//你不用面对房东,直接找中介租房即可
proxy.rent();
}
}
代理模式的好处:
- 可以使真实角色的操作更加纯粹,不用去关注一些公共的业务。
- 公共业务就交给代理对象去做,实现业务的分工。
- 公共业务发生扩展的时候,方便集中管理。
缺点:
- 一个真实角色就会产生一个代理角色;代码量会翻倍,导致开发效率变低
动态代理
- 动态代理和静态代理角色一样
- 动态代理的代理类是动态生成的,不是我们直接写好的
- 动态代理分成两大类:基于接口的动态代理,基于类的动态代理
- 基于接口---JDK动态代理
- 基于类:cglib
- 字节码文件实现:javassist
需要了解两个类:Proxy:代理,InvocationHandler:调用处理程序
动态代理的好处:
- 可以使真实角色的操作更加纯粹,不用去关注一些公共的业务。
- 公共业务就交给代理对象去做,实现业务的分工。
- 公共业务发生扩展的时候,方便集中管理。
- 一个动态代理类代理的是一个接口,一般对应的是一类业务。
- 一个动态代理类可以代理多个类只要是实现了同一个接口即可。
使用spring实现aop
【重点】使用aop注入,需要导入一个依赖包
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
方式一:使用Spring的API接口实现
<?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-->
<bean id="userService" class="com.xxx.service.UserServiceImpl"/>
<bean id="log" class="com.xxx.log.Log"/>
<bean id="afterLog" class="com.xxx.log.AfterLog"/>
<!--方式一:使用原生Spring API接口-->
<!-- 配置aop:需要导入aop的约束-->
<aop:config>
<!--切入点:expression:表达式。execution(要执行的位置 * * * * *)-->
<aop:pointcut id="pointcut" expression="execution(* com.xxx.service.UserServiceImpl.*(..))"/>
<!--执行环绕增加-->
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
</aop:config>
</beans>
方式二:自定义AOP实现【切面定义】
<?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-->
<bean id="userService" class="com.xxx.service.UserServiceImpl"/>
<bean id="log" class="com.xxx.log.Log"/>
<bean id="afterLog" class="com.xxx.log.AfterLog"/>
<!--方式二:自定义类-->
<bean id="diy" class="com.xxx.diy.DiyPointCut"/>
<aop:config>
<!-- 自定义切面,ref要引用的类 -->
<aop:aspect ref="diy">
<!--切入点-->
<aop:pointcut id="point" expression="execution(* com.xxx.service.UserServiceImpl.*(..))"/>
<!--通知-->
<aop:before method="before" pointcut-ref="point"/>
<aop:after method="after" pointcut-ref="point"/>
</aop:aspect>
</aop:config>
</beans>
方式三:使用注解方式实现AOP
<?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-->
<bean id="userService" class="com.xxx.service.UserServiceImpl"/>
<bean id="log" class="com.xxx.log.Log"/>
<bean id="afterLog" class="com.xxx.log.AfterLog"/>
<!-- 方式三:使用注解实现AOP-->
<bean id="annotationPointCut" class="com.xxx.diy.AnnotationPointCut"/>
<!--开启注解支持 JDK(默认 proxy-target-class="false") cglib(proxy-target-class="false)-->
<aop:aspectj-autoproxy/>
</beans>

浙公网安备 33010602011771号