在spring4以后,想要使用注解形式,必须得要引入aop的包5java
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>5.3.3</version> </dependency>
在配置文件当中,还得要引入一个context约束git
<?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:context="http://www.springframework.org/schema/context" 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"> </beans>
咱们以前都是使用 bean 的标签进行bean注入,可是实际开发中,咱们通常都会使用注解!web
一、配置扫描哪些包下的注解spring
<context:component-scan base-package="pojo"/>
二、在指定包下编写类,增长注解app
// 至关于配置文件中 <bean id="user" class="当前注解的类"/> @Component("user") public class User { public String name = "zc"; }
3.测试ide
@Test public void UserTest(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml"); User user = (User) applicationContext.getBean("user"); System.out.println(user.name); }
能够不提供set方法
,直接在属性名上添加@value(“xxx”)
学习
@Component("user") public class User { // 至关于配置文件中 <property name="name" value="秦疆"/> @Value("zc") public String name; }
测试结果成功测试
若是提供了set方法
,在set方法上添加@value(“xxx”)
this
@Component("user") public class User { public String name; @Value("zc") public void setName(String name) { this.name = name; } }
测试结果成功prototype
咱们这些注解,就是替代了在配置文件当中配置步骤而已!更加的方便快捷!
@Component三个衍生注解
为了更好的进行分层,Spring能够使用其它三个注解,功能同样,目前使用哪个功能都同样。
写上这些注解,就至关于将这个类交给Spring管理装配了!
做用域
@scope
@Component("user") @Scope("prototype") public class User { @Value("zc") public String name; }
总结
XML与注解比较
xml与注解整合开发 :推荐最佳实践
<context:annotation-config/>
做用:
咱们如今要彻底不使用spring的xml配置,全权交给java来作。
@Controller public class UserT { // 属性的注入 @Value("zcT") private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "User{" + "name='" + name + '\'' + '}'; } }
@Configuration:本质上也是一个Controller,也会被spring托管,注册到容器中
@Configuration:表示这是一个配置类,和以前的beans.xml的功能同样的
@ComponentScan:表示组件的扫描
@import:导入其余的配置类
@Bean:表示注册一个bean
@Configuration @ComponentScan("pojo") public class MyConfig { // 方法的名字便是bean中的id // 方法的返回值就是bean中的class @Bean public UserT getUserT(){ return new UserT(); // return就是返回要注入到bean中的对象 } }
@Test public void UserTTest(){ ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class); UserT userT = (UserT) context.getBean("getUserT"); System.out.println(userT.toString()); }
为何要学习代理模式,由于AOP的底层机制就是动态代理。
代理模式:
角色分析
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(); } //看房 public void seeHouse(){ System.out.println("带房客看房"); } //收中介费 public void fare(){ System.out.println("收中介费"); } }
public class Client { public static void main(String[] args) { // 房东要租房 Host host = new Host(); // 中介帮房东 Proxy proxy = new Proxy(host); // 去找中介 proxy.rent(); } }
分析:在这个过程当中,你直接接触的就是代理类(Proxy),就如同现实生活中的样子,你看不到房东,可是你依旧经过中介,租到了房东的房子,这就是所谓的代理模式。
静态代理的好处:
缺点 :
咱们在不改变原来的代码的状况下,实现了对原有功能的加强,这是AOP中最核心的思想。
动态代理的角色和静态代理的同样 .
动态代理的代理类是动态生成
的,静态代理的代理类是咱们提早写好
的
动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理
核心 : InvocationHandler 和 Proxy
【InvocationHandler:调用处理程序】
Object invoke(Object proxy, 方法 method, Object[] args); //参数 //proxy - 调用该方法的代理实例 //method -所述方法对应于调用代理实例上的接口方法的实例。方法对象的声明类将是该方法声明的接口,它能够是代理类继承该方法的代理接口的超级接口。 //args -包含的方法调用传递代理实例的参数值的对象的阵列,或null若是接口方法没有参数。原始类型的参数包含在适当的原始包装器类的实例中,例如java.lang.Integer或java.lang.Boolean 。
【Proxy : 代理】
//生成代理类 public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(),this); }
//抽象角色:租房 public interface Rent { public void rent(); }
//房东 public class Host implements Rent{ public void rent() { System.out.println("出租房子"); } }
public class ProxyInvocationHandler implements InvocationHandler { private Rent rent; public void setRent(Rent rent) { this.rent = rent; } //生成代理类,重点是第二个参数,获取要代理的抽象角色!以前都是一个角色,如今能够代理一类角色 public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(),this); } // proxy : 代理类 method : 代理类的调用处理程序的方法对象. // 处理代理实例上的方法调用并返回结果 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //核心:本质利用反射实现! Object result = method.invoke(rent, args); fare(); return result; } //看房 public void seeHouse(){ System.out.println("带房客看房"); } //收中介费 public void fare(){ System.out.println("收中介费"); } }
public class Client { public static void main(String[] args) { //真实角色 Host host = new Host(); //代理实例的调用处理程序 ProxyInvocationHandler pih = new ProxyInvocationHandler(); pih.setRent(host); //将真实角色放置进去 Rent proxy = (Rent)pih.getProxy(); //动态生成对应的代理类 proxy.rent(); } }
一个动态代理 , 通常代理某一类业务 , 一个动态代理能够代理多个类,代理的是接口
静态代理有的它都有,静态代理没有的,它也有!
- 能够使得咱们的真实角色更加纯粹 . 再也不去关注一些公共的事情 .
- 公共的业务由代理来完成 . 实现了业务的分工 ,
- 公共业务发生扩展时变得更加集中和方便 .
- 一个动态代理 , 通常代理某一类业务
- 一个动态代理能够代理多个类,代理的是接口!